Featured image of post Optimisation webperf : AVIF et pré-compression pour le blog

Optimisation webperf : AVIF et pré-compression pour le blog

Ecrit par ~ zwindler ~

Ce blog a presque 16 ans d’existence. Sur cette période, j’ai accumulé plus de 530 articles avec plus de 2700 images. Il y a quelques années, j’avais commencé à taper des limites (notamment quand j’ai essayer Gitlab pages chez Froggit) en atteignant les 500 Mo de medias.

J’avais fait une première passe d’optimisation, à grand coup de resize, jpegoptim et optipng et j’étais redescendu sous les 300 Mo. C’était pas mal, mais pas satisfaisant.

Puis j’ai vu le talk d’Antoine Caron (slashgear) et Mathieu Mure à Touraine Tech 2026 et j’ai enfin pris le temps de lâcher les “formats morts”.

Un peu de contexte

Ça fait un moment que je bricole l’infra et les perfs de ce blog. Si ça vous intéresse, les épisodes précédents sont ici :

Quand j’ai commencé ce round d’optimisation, la note PageSpeed de la page d’accueil tournait autour de 70-85 en mobile selon les articles. Pas dramatique, mais on peut faire mieux !

Le talk qui a tout déclenché

À Touraine Tech 2026, Antoine Caron et Mathieu Mure ont fait un talk très clair sur l’optimisation des images web, qui pourrissent les perfs des sites web aujourd’hui.

Le message principal : les formats comme JPEG et PNG sont des “formats morts” (ou en tout cas vieillissants). À compression équivalente, les formats modernes comme AVIF prennent beaucoup moins de place, mais surtout, ils affichent des artefacts visuels bien moindres dans les hauts niveaux de compression.

J’avais failli faire une migration vers le WebP il y a quelques années, puis j’avais laissé tomber, par flemme et après quelques soucis techniques dont je ne me souviens plus trop.

Et finalement, c’est presque tant mieux, parce qu’avec AVIF, on peut compresser encore plus fort, sans que ça se voit. C’est exactement ce qu’il me fallait.

Side note : on m’a demandé une comparaison WebP vs AVIF, et Joseph a trouvé ça. C’est plutôt intéressant :

Conversion massive en AVIF

J’ai donc écrit un script qui :

  1. Redimensionne les images trop grandes (> 1500px) pour les ramener à ~1 mégapixel
  2. Convertit en AVIF avec avifenc (qualité 50, speed 6)
  3. Met à jour les références dans tous les articles markdown

Et je l’ai lancé année par année, de 2026 jusqu’à 2010.

Les résultats

AnnéeFichiersOriginauxAVIFRéduction
2010120.4 MiB0.1 MiB74%
2011271.8 MiB0.7 MiB63%
201260.4 MiB0.1 MiB78%
201320.1 MiB0.1 MiB56%
2014435.3 MiB1.0 MiB81%
201521410.7 MiB3.7 MiB65%
201623112.1 MiB4.1 MiB66%
201742823.7 MiB9.1 MiB62%
20181427.5 MiB2.4 MiB68%
201913612.1 MiB2.9 MiB76%
202022823.6 MiB5.6 MiB77%
202118731.6 MiB4.8 MiB85%
202223729.2 MiB7.5 MiB74%
202325343.2 MiB7.8 MiB82%
202425934.2 MiB8.0 MiB77%
202525531.2 MiB6.8 MiB78%
2026446.8 MiB1.8 MiB74%
Total2704~274 MiB~66 MiB~76%

De PNG/JPEG qualité 90 à AVIF qualité 50 : entre 4 et 5 fois moins lourd.

Le plus satisfaisant, c’est que je ne suis pas capable de détecter visuellement de perte de qualité. Les screenshots de terminal et mes photos passent très bien en AVIF 50.

Pré-compression des documents HTML

Après la conversion AVIF, Antoine Caron (@slashgear.dev) m’a fait remarquer un truc :

Alors c’est pas mal déjà ! Je vois aussi que tes documents HTML ne sont pas compressés. Si ton blog est purement static, hésite pas à précompresser à balle et dire à ton server de servir les versions précompressées.

Effectivement, j’avais déjà gzip on; dans ma config nginx, mais c’est de la compression à la volée. Nginx utilise par défaut un niveau de compression modéré (niveau 6 sur 9) pour ne pas consommer trop de CPU.

server {
  server_name blog.zwindler.fr;
  root /usr/share/nginx/html/blog.zwindler.fr/public;
  gzip on;
  ...
}

Or, mon blog est 100% statique. Les fichiers ne changent qu’au rebuild. Ça veut dire qu’on peut les compresser une seule fois, avec le niveau maximum, et demander à nginx de servir directement les fichiers pré-compressés. Zéro CPU à chaque requête, mais surtout un meilleur ratio au final, car on peut compresser plus fort.

Côté build : blog_refresh.sh

J’ai ajouté les commandes de pré-compression après le hugo --minify :

# Pre-compress static files (gzip + brotli) for nginx gzip_static/brotli_static
find public -type f \( -name "*.html" -o -name "*.css" -o -name "*.js" \
  -o -name "*.xml" -o -name "*.json" -o -name "*.svg" -o -name "*.txt" \) \
  -exec gzip -k -f -9 {} +

# Brotli pre-compression (better ratio than gzip, ~15-25% smaller)
if command -v brotli &> /dev/null; then
  find public -type f \( -name "*.html" -o -name "*.css" -o -name "*.js" \
    -o -name "*.xml" -o -name "*.json" -o -name "*.svg" -o -name "*.txt" \) \
    -exec brotli -k -f -q 11 {} +
fi

Chaque fichier index.html se retrouve ainsi avec un index.html.gz et un index.html.br à côté de lui.

Côté nginx

# Serve pre-compressed files generated at build time
gzip_static on;
brotli_static on;  # nécessite libnginx-mod-http-brotli-static

# Fallback pour les contenus non pré-compressés
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css text/xml text/javascript
           application/javascript application/json
           application/xml image/svg+xml;

Pour Brotli, sur Ubuntu 24.04+, les paquets sont dans les dépôts officiels :

sudo apt install libnginx-mod-http-brotli-filter libnginx-mod-http-brotli-static

Le gain mesuré

Un petit curl pour comparer la page d’accueil :

# Avec Brotli (ce que reçoivent les navigateurs)
curl -so /dev/null -w "%{size_download}" -H "Accept-Encoding: br, gzip" https://blog.zwindler.fr/
# => 6 206 bytes

# Sans compression
curl -so /dev/null -w "%{size_download}" -H "Accept-Encoding: identity" https://blog.zwindler.fr/
# => 32 886 bytes

-81% sur le HTML, de 33 Ko à 6 Ko transférés. Et on le vérifie dans Chrome DevTools : le header Content-Encoding: br confirme que Brotli est bien servi.

Et c’est pareil pour les autres fichiers textes statiques (CSS, JS).

Bilan

OptimisationAvantAprèsGain
Images (AVIF)274 MiB66 MiB-76%
HTML page d’accueil (Brotli)33 Ko transférés6 Ko transférés-81%

Le tout sans aucune dégradation visible de la qualité des images, et zéro impact CPU côté serveur pour la compression (puisqu’elle est faite au build).

Et des webperfs qui ont bien progressé, même en mobile :

Licensed under CC BY-SA 4.0

Vous aimez ce blog ou cet article ? Partagez-le avec vos amis !   Twitter Linkedin email Facebook

Vous pouvez également vous abonner à la mailing list des articles ici

L'intégralité du contenu appartenant à Denis Germain (alias zwindler) présent sur ce blog, incluant les textes, le code, les images, les schémas et les supports de talks de conf, sont distribués sous la licence CC BY-SA 4.0.

Les autres contenus (thème du blog, police de caractères, logos d'entreprises, articles invités...) restent soumis à leur propre licence ou à défaut, au droit d'auteur. Plus d'informations dans les Mentions Légales

Généré avec Hugo
Thème Stack conçu par Jimmy