Optimisation des images avec Cecil

Cecil, mon générateur de site statique, permet de manipuler des ressources web (assets) tels que les images, les feuilles de styles (CSS ou Sass), les scripts, etc.

Dans le cas des images, on peut considérer qu’il en existe de deux types selon l’usage :

  1. les images habillant les templates
  2. les images illustrant le contenu des pages

Dans la suite de cet article je vais me concentrer sur les images contenues dans les pages, et comment elles sont optimisées par Cecil.

Image d'illustration
Illustration de unDraw

Ajout d'une image

Le contenu des pages étant rédigé en Markdown, les images sont contribuées via la syntaxe suivante :

![Description alternative](/image.jpg)

La balise HMTL générée sera de la forme :

<img src="/image.jpg" alt="Description alternative">

Optimisation automatique

En l’état l’image s’affichera correctement dans un navigateur web, mais nécessiterait d’être « retraitée » pour de meilleures performances.

Ainsi, en activant les options adéquates, Cecil ne se contente pas de générer une balise image comme indiqué ci-dessus : la balise est enrichie et le fichier est optimisé.

Par exemple, considérons une image image.jpg au format JPEG, de dimensions 800 x 600 pixels :

![Description alternative](/image.jpg "Titre de l'image")

Avec les options assets et body suivantes (paramétrées via le fichier config.yml) :

# Paramétrage global des assets de type image
assets:
  images:
    optimize:
      enabled: true
    quality: 75
    responsive:
      widths: [480, 640, 768, 1024]
      sizes:
        default: '(max-width: 480px) 480px, (max-width: 640px) 640px, (max-width: 800px) 768px, (max-width: 1600px) 1024px'
# Paramétrage des images au sein du contenu d'une page
body:
  images:
    lazy:
      enabled: true
    decoding:
      enabled: true
    webp:
      enabled: true
    responsive:
      enabled: true
    caption:
      enabled: true

Le rendu sera :

<figure>
  <picture title="Titre de l'image">
    <source type="image/webp"
      srcset="/assets/thumbnails/480/image.webp 480w,
              /assets/thumbnails/640/image.webp 640w,
              /assets/thumbnails/768/image.webp 768w,
              /image.webp 800w"
      sizes="(max-width: 480px) 480px, (max-width: 640px) 640px, (max-width: 800px) 768px, (max-width: 1600px) 1024px"
    >
    <img src="/image.jpg"
      alt="Description alternative"
      width="800"
      height="600"
      loading="lazy"
      decoding="async"
      srcset="/assets/thumbnails/480/image.jpg 480w,
              /assets/thumbnails/640/image.jpg 640w,
              /assets/thumbnails/768/image.webp 768w,
              /image.jpg 800w"
      sizes="(max-width: 480px) 480px, (max-width: 640px) 640px, (max-width: 800px) 768px, (max-width: 1600px) 1024px"
    >
  </picture>
  <figcaption>Titre de l'image</figcaption>
</figure>

Description :

  • Le fichier original est copié et compressé ;
  • Les attributs width et height sont déterminés automatiquement depuis les propriétés du fichier ;
  • L'attribut loading="lazy" est ajouté ;
  • L'attribut decoding="async" est ajouté ;
  • Les déclinaisons responsives sont générées (selon les options de configuration) ;
  • Une source alternative au format WebP est générée (également avec ses déclinaisons responsives) ;
  • Si un titre est ajouté alors la balise <image> est encapsulée dans une balise <figure> afin d'y ajouter une balise <figcaption> contenant le texte correspondant (acceptant le format Markdown, afin d’y mettre un lien vers la source par exemple).

À propos des images responsives

Afin d’automatiser le traitement, Cecil propose la configuration suivante par défaut :

  • redimensionnement automatique de l’image source selon les largeurs d’affichage les plus communes : 480, 640, 768, 1024, 1366, 1600, 1920 ;
  • application de la largeur maximum via l’attribut size : 100vw.

Mais bien entendu l’objectif est également de permettre la personnalisation de ces configurations afin d’adapter la génération au design du site, par exemple :

assets:
  images:
    responsive:
      widths: [480, 640, 768, 1024]
      sizes:
        default: '(max-width: 480px) 480px, (max-width: 640px) 640px, (max-width: 800px) 768px, (max-width: 1600px) 1024px'

Gains de performance

Grâce à ces optimisations automatique, les gains de performance sont non négligeables :

  • Le temps de chargement des pages contenant des images est accéléré via :
    1. La compression du fichier d’origine (avec une qualité cible de 75%, suffisante pour un affichage web) ;
    2. L’ajout d'une alternative dans un format « moderne » (WebP) plus léger et supporté par la majorité des navigateurs web ;
    3. La proposition de différentes dimensions (images responsives ou images adaptatives en français), permettant au navigateur web d'utiliser celle qui est la plus adaptée à la zone d'affichage (viewport) ;
    4. L’ajout de la balise loading="lazy" permettant de ne charger que les images « visibles » (au dessus de la ligne de flottaison) ;
    5. L’ajout de la balise decoding="async" permettant de continuer à charger le contenu d’une page sans attendre celui des images.
  • L’ajout des dimensions évite le phénomène de Cumulative Layout Shift (CLS).

Illustration avec l'outil de mesure PageSpeed sur la page que vous êtes en train de consulter :

Résultat des performances mesurées via l'outil PageSpeed : 98/100
98/100 sur PageSpeed.

Conclusion

Comme vous pouvez le constater, l’objectif est de simplifier le travail des personnes en charge de la rédaction des contenus, qui n’ont ainsi pas à se soucier d’optimiser manuellement (ou via des outils externes) leurs images d’illustration.

Si vous souhaitez en savoir plus, je vous invite à consulter la documentation des images de Cecil.