Qu’est-ce que le rendu progressif ?
Le rendu progressif présente des portions utilisables ou des versions de plus en plus complètes du contenu à mesure que les données deviennent disponibles. Il évite de retenir l’intégralité du résultat jusqu’à ce que chaque ressource ou phase de traitement soit terminée.
Fonctionnement du rendu progressif
Le rendu progressif est une stratégie qui couvre l’encodage, le transport, l’analyse syntaxique et la présentation ; ce n’est pas un format multimédia unique. Au niveau du fichier, un JPEG progressif stocke l’image sous forme d’une série de balayages de qualité croissante. Un décodeur peut ainsi afficher une version peu détaillée de l’image entière dès le premier balayage et l’affiner à mesure que les suivants arrivent. Un PNG entrelacé transmet quant à lui ses pixels en sept passes. Au niveau du document, un serveur peut transmettre le HTML en flux pour que le navigateur affiche la structure externe de la page et les éléments de substitution pendant que les sections plus lentes sont encore en cours de production. Le moteur de rendu serveur en flux de React, par exemple, envoie d’abord le contenu de repli d’une limite <Suspense>, puis le contenu réel. Ces deux niveaux répondent à des attentes différentes : la décomposition du Largest Contentful Paint par web.dev comptabilise séparément le délai jusqu’au premier octet du document HTML et le temps de chargement de la ressource image elle-même. Envoyer le document plus tôt ne raccourcit donc pas le téléchargement d’une image qu’il référence, même si le navigateur peut commencer ce téléchargement plus tôt lorsque le HTML reçu en avance contient déjà l’URL de l’image. Dans les deux cas, le résultat anticipé n’est utile que s’il atteint réellement l’écran plus tôt ; réserver l’espace du résultat final évite que son remplacement déplace la mise en page environnante.
Points clés
- Quels formats d’image permettent un rendu progressif ? JPEG lorsqu’il est encodé en mode progressif, PNG et GIF lorsqu’ils sont entrelacés, ainsi que JPEG XL, même si MDN précise que Safari n’affiche JPEG XL qu’après le téléchargement complet. WebP ne peut pas affiner un aperçu de l’image entière : la FAQ WebP de Google indique qu’il ne propose aucun rafraîchissement progressif ou entrelacé au sens de JPEG ou PNG, mais seulement un décodage incrémental qui affiche les lignes à mesure que leurs octets arrivent. Pour AVIF, cela dépend de l’encodage et du logiciel de visualisation. La spécification AVIF prend en charge le décodage progressif au moyen d’images en couches, mais laisse le moteur de rendu libre de n’afficher que la couche la plus élevée ;
avifencde libavif produit un tel fichier avec--progressive, et le journal des modifications de libavif cite Chrome comme logiciel affichant les couches progressivement. Le guide des formats de MDN indique au contraire qu’AVIF ne prend pas en charge le rendu progressif et que les fichiers doivent être entièrement téléchargés avant l’affichage. Il ajoute que la taille réduite des fichiers AVIF compense souvent cette limite, sauf pour les fichiers plus volumineux. Une conversion en WebP ou AVIF ne préserve donc pas à elle seule l’affichage initial peu détaillé : pour AVIF, vérifiez le réglage de l’encodeur et les navigateurs cibles ; sinon, un élément de substitution distinct doit assurer cet effet. - Quel est le coût d’un JPEG progressif ? Principalement du travail de décodage, plutôt que de la taille de fichier. La documentation de libjpeg indique que les fichiers progressifs sont souvent légèrement plus petits que les fichiers séquentiels de même qualité et que l’image finale est identique. Elle précise aussi que chaque balayage affiché nécessite à peu près autant de travail de décodage qu’une image complète de mêmes dimensions, et que les balayages intermédiaires ne sont affichés que si l’application utilise le mode d’image en mémoire tampon de la bibliothèque ; sinon, le décodeur lit tous les balayages et ne renvoie que l’image finale. La visibilité de cet affinement pour les utilisateurs dépend donc du décodeur utilisé, et pas seulement du fichier.
- Pourquoi une page transmise en flux apparaît-elle encore d’un seul coup ? Généralement, un élément entre le moteur de rendu et le navigateur retient les octets. nginx met par défaut les réponses transmises par proxy en mémoire tampon et ne transmet les données au fur et à mesure de leur réception que si
proxy_bufferingest désactivé ou si le serveur en amont envoieX-Accel-Buffering: no, un en-tête que l’on peut demander à nginx d’ignorer avecproxy_ignore_headers. Le guide d’auto-hébergement de Next.js ajoute que certains équilibreurs de charge cloud mettent les réponses en mémoire tampon par défaut et que les proxys inverses entre l’équilibreur de charge et l’application doivent aussi transmettre les réponses fragmentées sans mise en mémoire tampon. La compression met une fenêtre de sortie en mémoire tampon pour bien compresser ; le README decompressionpour Express décrit ce comportement pour les événements envoyés par le serveur et fournitres.flush()pour forcer l’envoi au client de la réponse partiellement compressée. L’application peut elle-même annuler cet effet : React indique que démarrer le flux dansonAllReadyplutôt que dansonShellReadyne permet pas de chargement progressif. Même lorsque les octets arrivent tôt, du CSS ou du JavaScript chargé au préalable peut encore bloquer le rendu. - Le chargement progressif provoque-t-il des décalages de mise en page ? Il peut en provoquer lorsque l’espace destiné au contenu tardif n’est pas réservé. Les recommandations de Google sur le Cumulative Layout Shift citent les images sans dimensions et le contenu injecté dynamiquement parmi les causes les plus courantes d’un mauvais score. Elles préconisent de toujours définir
widthetheightsur les images et les vidéos, ou de réserver l’espace avec la propriété CSSaspect-ratio. Une image qui s’affine dans un cadre de dimensions connues ne déplace rien autour d’elle ; un contenu de remplacement dont la taille diffère de celle de son élément de substitution peut déplacer le contenu environnant, sauf si un conteneur réserve déjà l’espace.
Quand le rendu progressif est utile
Prévoyez un rendu progressif lorsque le contenu important d’une page ou d’un média peut être affiché en priorité, avant les détails secondaires. Des dimensions instables ou des mises à jour mal ordonnées peuvent au contraire provoquer des décalages de mise en page et des changements visuels gênants.
Comment Transloadit contribue au rendu progressif
Le Robot /image/resize de Transloadit dispose d’un paramètre progressive qui entrelace la sortie afin que les navigateurs puissent d’abord afficher une version basse résolution de l’image entière ; ce paramètre est désactivé par défaut. Pour les formats auxquels cela ne s’applique pas, un Step qui produit une image peut extraire un BlurHash ou un ThumbHash via output_meta, un espace réservé compact à afficher pendant le chargement de l’image complète. Les résultats d’image dans l’Assembly Status contiennent également width, height et aspect_ratio dans leurs métadonnées, ce qui permet à une page de réserver l’emplacement de l’image avant son arrivée.
La documentation du Robot indique une augmentation de la taille du fichier avec progressive sans préciser les formats de sortie concernés, ce qui diffère de ce que dit la documentation de libjpeg sur le JPEG progressif ci-dessus. Effectuez donc des mesures avec vos propres images et votre format de sortie. L’extraction de ThumbHash est facturée au titre des métadonnées ; consultez la documentation du Robot pour connaître les conditions actuelles.
Références
- libjpeg-turbo : documentation de la bibliothèque libjpeg (prise en charge du JPEG progressif et mode d’image en mémoire tampon)
- Spécification PNG du W3C, troisième édition (entrelacement et extraction des passes)
- MDN : guide des types et formats de fichiers image
- Google : questions fréquentes sur WebP (affichage progressif ou entrelacé)
- Spécification AV1 Image File Format (AVIF) v1.2.0 (périmètre et éléments d’image en couches)
- libavif : manuel d’avifenc (options --progressive et --layered)
- Journal des modifications de libavif (encodage AVIF en couches et rendu progressif dans les logiciels de visualisation)
- React : renderToPipeableStream (transmission en flux, structure de base et contenus de repli de Suspense)
- nginx : ngx_http_proxy_module (proxy_buffering et X-Accel-Buffering)
- Next.js : guide d’auto-hébergement (transmission en flux et mise en mémoire tampon par les proxys)
- README du middleware de compression d’Express (res.flush et sortie mise en mémoire tampon)
- Glossaire MDN : blocage du rendu
- web.dev : optimiser le Largest Contentful Paint (composantes du LCP)
- web.dev : optimiser le Cumulative Layout Shift