Hugo : Optimisation des images WebP et CI/CD sur GitLab

En 2018, je vous expliquais comment j’avais migré mon WordPress vers Hugo. Depuis, Hugo est resté mon outil de prédilection pour ce blog. Cependant, avec le temps et l’accumulation d’articles, j’ai dû optimiser mon flux de travail, notamment pour la gestion des images et l’automatisation du déploiement.

L’importance de l’optimisation des images

Les images sont souvent l’élément le plus lourd d’une page web. Pour garantir un chargement rapide, il est essentiel d’utiliser des formats modernes comme le WebP, qui offre une compression supérieure au JPEG ou au PNG sans perte de qualité visible.

Automatiser la conversion avec ImageMagick

Voici comment j’utilise ImageMagick pour convertir les images :

# Cas général pour JPG et PNG
magick "${SRC_IMAGE}" \
    -colorspace sRGB \
    -filter Lanczos \
    -resize "2560x2560>" \
    -quality 80 \
    -define webp:method=4 \
    -define webp:smart-subsample=true \
    -strip \
    "${DEST_IMAGE}"

Voici le détail des options utilisées pour garantir le meilleur compromis poids/qualité :

  • -colorspace sRGB : Force l’espace colorimétrique sRGB, standard pour le web, évitant les surprises de rendu entre navigateurs.
  • -filter Lanczos : Utilise un filtre de rééchantillonnage de haute qualité pour le redimensionnement, offrant une netteté supérieure.
  • -resize "2560x2560>" : Redimensionne l’image pour qu’elle tienne dans un carré de 2560px de côté, mais uniquement si l’image originale est plus grande (grâce au suffixe >).
  • -quality 80 : Règle le niveau de compression à 80. C’est le “sweet spot” habituel pour le WebP.
  • -define webp:method=4 : Définit l’effort de compression (de 0 à 6). Le niveau 4 offre un excellent équilibre entre temps de calcul et gain de place.
  • -define webp:smart-subsample=true : Active l’échantillonnage intelligent des couleurs, ce qui préserve mieux les détails sur les bords contrastés.
  • -strip : Supprime toutes les métadonnées (EXIF, profils ICC, commentaires) souvent inutiles sur le web, allégeant encore le fichier final.

Cela redimensionne intelligemment, retire les métadonnées inutiles.

Un pipeline CI/CD robuste sur GitLab

Le déploiement est la pierre angulaire de l’automatisation. Mon fichier .gitlab-ci.yml a bien évolué depuis mes débuts. Il permet désormais de gérer la compilation, l’indexation pour la recherche et la compression des assets.

Analyse du fichier .gitlab-ci.yml

J’utilise une image Docker officielle d’Hugo augmentée des outils nécessaires :

image: docker.io/hugomods/hugo:0.161.1

before_script:
  - apk add --no-cache curl ca-certificates openssl git findutils brotli imagemagick imagemagick-jpeg
script:
  - npm install -g pagefind
  - hugo --gc --minify --baseURL
  - pagefind

Voici un schéma récapitulatif du flux de travail du pipeline :

Le processus de construction (build) se déroule en plusieurs étapes clés :

  1. Installation de Pagefind : Pour la recherche statique sur le site.
  2. Génération du site : Utilisation des flags --gc (nettoyage) et --minify (minification).
  3. Indexation : Lancement de pagefind pour mettre à jour l’index de recherche.
  4. Compression post-build : Une étape cruciale pour les performances serveur.
after_script:
  - find public/ -type f -regex '.*\.\(css\|html\|js\|txt\|xml\)$' -exec gzip -f -k {} \;
  - find public/ -type f -regex '.*\.\(css\|html\|js\|txt\|xml\)$' -exec brotli -f -k {} \;

En générant des versions .gz et .br de mes fichiers texte (HTML, CSS, JS), je permets au serveur (GitLab Pages ou Cloudflare) de servir directement les fichiers compressés, réduisant ainsi drastiquement le temps de transfert.

Intégration de Pagefind dans le thème

Pour que la recherche soit efficace, Pagefind doit savoir quoi indexer et comment extraire les métadonnées. Cela passe par quelques ajustements dans les fichiers de template de Hugo.

1. Marquer le contenu principal

Dans le template layouts/_default/single.html du thème, j’ai ajouté l’attribut data-pagefind-body sur la balise <article>. Cela indique à Pagefind que seul le contenu de l’article doit être indexé, excluant ainsi les menus, le pied de page et les barres latérales :

<article role="main" class="blog-post" data-pagefind-body>
  {{ .Content }}
</article>

2. Exploiter les balises SEO

Pagefind peut extraire des métadonnées (titre, date, tags, image) directement depuis les balises HTML ou les balises meta, l’inclusion des partials standard de Hugo permet de générer ces informations a partir des templates internes d’Hugo:

{{- partial "schema.html" . }}
{{- partial "opengraph.html" . }}
{{- partial "twitter_cards.html" . }}

3. Configuration via pagefind.yml

Enfin, le fichier pagefind.yml à la racine du projet permet de configurer finement le comportement de l’indexeur. On y définit notamment le dossier de sortie, les langues supportées et le mappage des métadonnées :

# Pagefind configuration
site: public
output_subdir: pagefind

# Cible uniquement les articles (pattern année/mois/slug)
glob: "[0-9][0-9][0-9][0-9]/[0-9][0-9]/*/index.html"

# Extraction des métadonnées depuis les balises Open Graph
indexing_options:
  - metadata_fields:
      - { tag: "meta[property='og:title']", as: "title", content_attr: "content" }
      - { tag: "meta[property='article:published_time']", as: "date", content_attr: "content" }
      - { tag: "meta[property='article:tag']", as: "tags", content_attr: "content" }

Cette configuration permet d’avoir une recherche rapide, pertinente et parfaitement intégrée au reste de l’écosystème.

Conclusion

L’utilisation d’Hugo ne se limite pas à écrire du Markdown. En intégrant des outils comme ImageMagick pour le WebP et en peaufinant votre pipeline GitLab CI, vous transformez votre blog en une machine de guerre ultra-rapide et facile à maintenir.

Si vous n’avez pas encore sauté le pas de l’automatisation, c’est le moment idéal pour optimiser vos assets et votre déploiement !

Catégories : DevOps 

Suggestions de lecture :