
🌐 Aussi en: English · Deutsch · Español
Mon blog me semblait lourd. La page d’accueil pesait environ 1,5 Mo et mon premier réflexe
a été de soupçonner les coupables habituels : c’est peut-être la base de données, je devrais peut-être passer MariaDB
à la version majeure suivante, le TLS a peut-être besoin d’être optimisé. Grand classique du développeur
– dégainer le correctif avant d’avoir trouvé le bug. Cette fois, j’ai donc d’abord fait la chose
ennuyeuse mais correcte : j’ai mesuré. Les résultats ont été une
gifle salutaire. 📏
🩺 Étape 1 : trouver le vrai goulot d’étranglement
Time to First Byte, trois essais depuis un client à peu près froid :
TTFB 0.173s | Total 0.174s | HTTP/2
TTFB 0.170s | Total 0.171s | HTTP/2
TTFB 0.185s | Total 0.187s | HTTP/20,17 seconde. Le serveur livre le HTML quasi instantanément. Le HTML lui-même,
compressé en gzip sur le réseau, fait environ 18 Ko. Donc la base de données, PHP, les couches de cache – tout
ce que j’étais tenté d’« optimiser » – ne sont pas le problème.
Le slow query log était d’accord : zéro entrée. La base ne transpire jamais, parce que
le cache d’objets Redis absorbe les requêtes répétitives avant même qu’elles ne l’atteignent.
Passer MariaDB à une nouvelle version majeure ne m’aurait strictement rien apporté. 🤷
Les 1,5 Mo venaient presque entièrement d’une seule chose : les images. Environ un
mégaoctet. Mystère résolu avant même d’avoir touché un seul fichier de configuration.
😤 Étape 2 : les images étaient déjà… plutôt bonnes
Et voilà le côté agaçant : les images n’étaient pas un gain facile. Elles étaient
déjà en WebP (une extension de compression s’en charge),
en lazy loading (46 sur 46 avec loading="lazy") et
servies avec des srcset/sizes corrects, si bien que les vignettes chargent la petite
variante et non la géante. Multiplexage HTTP/2, gzip, CSS/JS agrégés –
tout était déjà en place. Ce n’était pas un site négligé, mais un site bien optimisé
qui est simplement riche en images (une page d’accueil pleine de vignettes d’articles).
Les gains restants étaient donc petits et très ciblés. Deux, exactement.
🔐 Levier 1 : ECDSA au lieu de RSA (l’ajustement TLS honnête)
Le certificat était en RSA-2048. Les signatures RSA sont relativement coûteuses à calculer
pour le serveur pendant le handshake, j’ai donc configuré cert-manager pour émettre un certificat
feuille ECDSA P-256 – handshake moins coûteux, sécurité équivalente
(voire meilleure). Dans une configuration cert-manager/ingress-shim, cela tient en trois
annotations :
cert-manager.io/private-key-algorithm: "ECDSA"
cert-manager.io/private-key-size: "256"
cert-manager.io/private-key-rotation-policy: "Always"cert-manager a réémis le certificat en quatre secondes environ, sans interruption, et
openssl a confirmé le changement : Public-Key: (256 bit) … NIST. Est-ce que j’avoue en toute honnêteté que c’est un gain minuscule ? Oui.
CURVE: P-256
Grâce à HTTP/2, le handshake n’a lieu qu’une fois par page et prenait déjà environ 44 ms.
Mais c’est gratuit et permanent, donc : adopté. ✅
🖼️ Levier 2 : AVIF – quand « converti » ≠ « livré »
L’AVIF bat généralement le WebP de 20 à 40 % à qualité égale, j’ai donc demandé à
l’extension de tout convertir. Elle a docilement produit 955 fichiers AVIF,
environ 60 % plus légers sur disque que les originaux WebP. Parfait. J’ai remesuré en m’attendant
à une page plus légère, et j’ai obtenu…
<picture> tags: 0 | .avif references: 0 | .webp references: 220
image weight: 1066 KB (identical to before)Rien. Les fichiers AVIF existaient, étaient même accessibles en HTTP, mais la page
servait toujours 100 % de WebP – même quand je demandais avec
Accept: image/avif. C’est le piège classique « extension d’images nouvelle génération
contre reverse proxy nginx ». La plupart de ces extensions livrent
l’AVIF via des règles de réécriture côté serveur (.htaccess d’Apache ou
snippets nginx). Mon WordPress tourne derrière un sidecar nginx dans K3s
dont la configuration est gérée par Ansible – les règles de réécriture générées automatiquement par l’extension
n’y arrivent jamais. Les images converties restaient donc sur le disque, à s’admirer
elles-mêmes. 🪞
Reconstruire le cache de pages n’a servi à rien – parce que le cache n’a jamais été le
problème, c’était la livraison. La solution a été de faire passer l’extension de la réécriture serveur
à la méthode de livraison balise picture / HTML, qui
injecte l’AVIF au moment du rendu :
<picture>
<source type="image/avif" srcset="….webp.avif">
<img src="….webp"> <!-- fallback for the ~5% without AVIF -->
</picture>On purge le cache pour que le HTML statique se régénère avec ces balises, et soudain le
navigateur a le choix – et il prend le fichier le plus léger.
📊 Le résultat
Les mêmes 20 images visibles, à périmètre identique :
Before (WebP): 1038 KB
After (AVIF): 642 KB
Savings: 396 KB → 38% lighterChaque image part désormais en image/avif vers les navigateurs compatibles AVIF
(~95 %+ des visiteurs) ; les autres se rabattent automatiquement sur le WebP via
le <img>. Aucun inconvénient, environ 40 % de poids d’images en moins. 🎯
🧠 Ce qu’il faut retenir
- 📏 Mesurez avant d’optimiser. Mon instinct disait « base de données / TLS / mise à jour de MariaDB ». Les données disaient « images ». L’instinct avait tort, et m’aurait coûté des heures pour un gain nul.
- 🚦 TTFB et poids de page sont deux problèmes distincts. Un TTFB de 0,17 s avec 1,5 Mo de charge utile signifie : laissez le backend tranquille, regardez ce que vous envoyez sur le réseau.
- 🖼️ « Converti en AVIF » ne veut pas dire « sert de l’AVIF ». Vérifiez de bout en bout – contrôlez les octets réellement transmis avec le bon en-tête
Accept, pas seulement l’existence des fichiers. - 🔌 Les réglages par défaut des extensions supposent Apache. Avec un reverse proxy nginx / K3s, la livraison par « réécriture » ne fait silencieusement rien ; la méthode balise picture est votre amie.
- ✅ Prenez quand même les gains gratuits. ECDSA plutôt que RSA ne changera pas votre vie, mais c’est permanent et ça ne coûte rien.
Comme toujours, toute la pile – la configuration de cert-manager, celle de nginx, absolument
tout – est publique et versionnée dans mon dépôt Ansible :
github.com/aptupgrademe/www_k3s.
Mesurez donc votre propre site un de ces jours. Vous pourriez être surpris par ce qui est vraiment lent. 🧑💻




