Les inscriptions sont fermées. Menestrel sert désormais aux sites réalisés par Agora Studio, agence web dans la Loire.

Les images dans Astro : ce qu'un CMS devrait faire à votre place

Votre client envoie une photo de quatre mégaoctets depuis son téléphone, de travers. Tout ce qui doit se passer ensuite, ce qu'Astro prend en charge, et ce qu'un CMS devrait cesser de vous faire construire.

Voici une scène qui se produit sur chaque site client, plusieurs fois par an.

Votre client photographie sa nouvelle devanture un mardi après-midi. Le fichier fait 4,2 Mo, 4032 par 3024 pixels, en JPEG, avec une orientation EXIF à 6 parce qu’il tenait son téléphone en travers. Il l’envoie dans l’interface que vous lui avez donnée, et s’attend à ce qu’elle apparaisse correctement sur sa page d’accueil.

Entre cet envoi et une page rapide et correcte, il y a environ huit choses qui doivent arriver. Savoir lesquelles sont votre problème fait la différence entre un site qui reste rapide et un site qui se dégrade en silence sur deux ans.

Les huit choses

1. Accepter le fichier tout court. Les iPhone récents produisent du HEIC par défaut. Les navigateurs n’affichent pas le HEIC. Si votre chaîne ne convertit pas, le client envoie une photo, voit une image cassée, et conclut que l’outil est cassé.

2. Corriger l’orientation. L’orientation EXIF est une métadonnée qui dit « cette image est pivotée ». Certains moteurs la respectent, d’autres non, et une fois que vous redimensionnez sans en tenir compte, vous obtenez une photo de travers pour toujours. Retirez la métadonnée et appliquez réellement la rotation.

3. Retirer le reste des métadonnées. Cette photo contient des coordonnées GPS. Publier l’adresse du domicile d’un client parce qu’il a photographié quelque chose dans son jardin est un incident de confidentialité qui porte votre nom.

4. Redimensionner. Personne n’a besoin de 4032 pixels. Il vous faut un jeu de largeurs couvrant les mises en page où l’image apparaît, typiquement 400, 800, 1200 et 1600.

5. Convertir les formats. AVIF quand c’est possible, WebP en repli, et le format d’origine pour le reste. L’AVIF divise couramment par deux le poids d’une photo par rapport au WebP.

6. Servir depuis un CDN, avec des en-têtes de cache assez longs pour compter. Une image régénérée à chaque requête est une facture et un problème de latence.

7. Transporter les dimensions jusqu’au balisage. Largeur et hauteur sur la balise, ou un rapport d’aspect en CSS, pour que la page ne saute pas pendant le chargement. C’est l’essentiel de ce que mesure le Cumulative Layout Shift, et c’est la métrique la plus facile à rater.

8. Avoir un texte alternatif. Ce qui suppose que quelqu’un l’écrive, donc que l’interface le demande au moment de l’envoi, parce que personne n’y revient plus tard.

Ce qu’Astro prend en charge

Le composant <Image /> d’Astro et son service d’images sont réellement bons, et ils couvrent les points 4, 5 et 7 pour les images locales : les fichiers présents dans votre projet au moment de la construction. Importez une image, passez-la à <Image />, obtenez une sortie responsive avec les bonnes dimensions et des formats modernes.

Le piège est dans « au moment de la construction, dans votre projet ». Astro optimise ce qu’il voit. Une URL venant d’un CMS n’est, de son point de vue, qu’une chaîne de caractères. Il ne peut pas redimensionner ce qu’il n’a pas.

Il existe bien remotePatterns pour autoriser l’optimisation distante, ce qui aide, mais cela signifie que votre construction télécharge et traite chaque photo du client à chaque construction. Sur un site à deux cents images, cela transforme une construction rapide en construction lente, à chaque déploiement, indéfiniment.

Là où un CMS devrait prendre le relais

La répartition qui fonctionne : le CMS possède la chaîne de traitement, Astro possède le balisage.

Concrètement, au moment où votre construction voit une image, ce qui suit est déjà vrai : elle a été convertie, nettoyée, pivotée, redimensionnée en un jeu de déclinaisons, et posée derrière un CDN. Ce qui arrive dans votre contenu est une URL plus les métadonnées dont vous avez besoin, dimensions et texte alternatif compris.

Votre construction ne fait aucun travail d’image. Les déploiements restent rapides quel que soit le nombre de photos envoyées, parce que le traitement a eu lieu une fois, à l’envoi, plutôt qu’une fois par construction.

C’est ce que fait Menestrel. L’envoi est un PUT présigné directement vers le stockage objet, donc un gros fichier ne traverse jamais l’API. Le traitement se fait sur un worker : détection du format, gestion de l’EXIF, nettoyage des métadonnées, redimensionnement vers un jeu fixe de largeurs, déclinaisons AVIF et WebP. La diffusion passe par des URL imgproxy signées derrière un CDN européen, donc une déclinaison qui n’existe pas encore est générée une fois, mise en cache, et jamais recalculée.

Le côté composant reste alors trivial :

---
import { CmsImage } from '@menestrel/astro/components';
const { entry } = Astro.props;
---
<CmsImage image={entry.data.photo} sizes="(max-width: 720px) 100vw, 720px" />

Les dimensions viennent du contenu, donc pas de saut de mise en page. Le srcset est produit à partir des largeurs disponibles. Le texte alternatif vient de la médiathèque, où il a été recueilli à l’envoi.

Pourquoi traiter à l’envoi vaut mieux que traiter au build

C’est le point d’architecture de tout l’article, et il mérite d’être dit à part.

Si les images sont traitées pendant la construction, ce travail se répète à chaque déploiement. Changez un paragraphe sur un site à trois cents photos, et la construction télécharge, décode, redimensionne et ré-encode trois cents images pour produire une page où une phrase a changé. Le cache aide jusqu’à ce qu’il soit froid, c’est-à-dire précisément quand vous voudriez le moins : sur un conteneur d’intégration continue neuf, sur le déploiement que vous regardez parce qu’un client attend.

Si les images sont traitées à l’envoi, le travail a lieu une fois par image, définitivement. Votre construction reçoit des URL et des métadonnées. Un déploiement sur un site à deux mille photos coûte autant que sur un site sans photo.

L’effet indirect compte plus que la durée elle-même. Quand les déploiements sont lents, publier paraît lent, et toute la promesse du « votre client clique et le site se met à jour » se dégrade en « votre client clique et attend quatre minutes ». Nous visons une à trois minutes entre le clic et la page en ligne, et ce budget n’est tenable que parce que la construction ne fait aucun travail d’image.

Le problème du texte alternatif, qui est un problème de conception

Tous les CMS ont un champ de texte alternatif. La plupart des sites ont des textes alternatifs vides partout.

La raison tient à l’endroit où se trouve le champ. Si le texte alternatif est une case optionnelle sur un écran de médiathèque que le client visite une fois, il restera vide. S’il est demandé au moment de l’envoi, dans le flux, la plupart des clients le remplissent, parce qu’ils viennent de choisir la photo et savent ce qu’elle contient.

C’est une petite décision de conception avec un grand effet sur l’utilisabilité du site par une personne qui utilise un lecteur d’écran, et elle vaut la peine d’être vérifiée dans tout CMS que vous évaluez : où, exactement, demande-t-il le texte alternatif ?

La décision voisine est le point d’intérêt. Une photo recadrée en bandeau large et en vignette carrée ne peut pas être recadrée depuis le centre dans les deux cas sans couper une tête. Laisser l’éditeur poser un point d’intérêt une fois, et faire respecter ce point par toutes les déclinaisons, supprime toute une catégorie de messages « la photo est bizarre sur mobile ».

L’angle Core Web Vitals, brièvement

Deux des trois Core Web Vitals se jouent largement sur les images.

Le Largest Contentful Paint est en général l’image de bandeau. Ce qui aide : le bon format, la bonne taille pour la fenêtre, et ne pas la charger en différé. Ce dernier point est la blessure qu’on s’inflige le plus souvent, parce que le chargement différé est appliqué par défaut à tout, et que le bandeau est justement la seule image qui doit charger immédiatement. Si votre composant met tout en différé, votre bandeau est lent et aucune optimisation ailleurs ne compense.

Le Cumulative Layout Shift, ce sont les images sans dimensions. Si le navigateur ignore la hauteur d’une image, il ne réserve rien, puis réagence la page à l’arrivée des octets. C’est pour ça que les dimensions doivent voyager avec le contenu plutôt que d’être écrites en dur par gabarit.

L’Interaction to Next Paint est surtout du JavaScript, dont un site vitrine Astro n’a presque pas. Celui-là, vous l’obtenez gratuitement en ayant choisi un générateur de site statique.

La règle pratique : laissez le composant poser largeur et hauteur depuis le contenu, et gardez un moyen de marquer le bandeau comme prioritaire. Le nôtre accepte loading et fetchpriority pour exactement ça.

Où vit le quota

Les médias sont ce qui consomme réellement le stockage d’un site client. Le texte est négligeable, les photos sont tout.

Deux choses à vérifier dans n’importe quel CMS : si supprimer une image libère le quota, et si une image encore référencée par une version publiée peut être supprimée.

La seconde est subtile et compte. Si un client supprime une photo qu’une page publiée utilise encore, et que le système le laisse faire, le site en ligne casse. Si le système garde le fichier en silence, le quota est un mensonge. Le bon comportement est de refuser la suppression en disant pourquoi, ce que nous faisons : un fichier référencé par un instantané encore retenu ne peut pas être purgé, et l’interface indique quel instantané et jusqu’à quand.

Ce que nous ne faisons volontairement pas

Pas d’édition d’image au-delà du recadrage. Pas de filtres, pas de luminosité, pas de texte incrusté. Si un client a besoin de ça, il a besoin d’un éditeur photo, et il en existe de bons.

Un jeu fixe de largeurs. Vous ne pouvez pas demander une taille arbitraire. Cela garde le cache utile et le stockage borné, et cela signifie qu’une maquette réclamant une largeur inhabituelle doit prendre la plus proche au-dessus.

Les formats acceptés sont limités : JPEG, PNG, WebP, AVIF, GIF et PDF. Pas de SVG, volontairement, parce qu’un SVG est un document qui peut porter du script, et accepter des SVG arbitraires envoyés par des clients est un vecteur d’injection déguisé en image.

25 Mo par fichier, 4096 pixels au maximum. Assez pour toute photo de site vitrine, assez petit pour que le traitement reste prévisible.

La liste de contrôle

Si vous évaluez un CMS pour un site avec de vraies photos, demandez :

  1. Que se passe-t-il si j’envoie un HEIC depuis un iPhone ?
  2. Les métadonnées EXIF sont-elles retirées, et l’orientation appliquée ?
  3. Quelles largeurs et quels formats sortent, et sont-ils générés une fois ou à chaque construction ?
  4. Est-ce que je récupère les dimensions dans mon contenu, pour éviter les sauts de mise en page ?
  5. Où le texte alternatif est-il demandé ?
  6. Puis-je poser un point d’intérêt, et les recadrages le respectent-ils ?
  7. Que se passe-t-il si un client supprime une image utilisée par une page en ligne ?

La plupart de ces questions n’ont rien à voir avec la page marketing du CMS, et toutes affecteront le site de votre client pendant des années. Les comparatifs traitent plus largement la façon dont les principaux outils gèrent l’édition.

Retour au blog