Découvrez comment votre serveur peut envoyer des indices au navigateur concernant les sous-ressources critiques.
Qu'est-ce que les premiers indices ?
Les sites Web sont devenus plus sophistiqués au fil du temps. Par conséquent, il n'est pas rare qu'un serveur doive effectuer des tâches non triviales (par exemple, accéder à des bases de données ou à des CDN accédant au serveur d'origine) pour générer le code HTML de la page demandée. Malheureusement, ce "temps de réflexion du serveur" entraîne une latence supplémentaire avant que le navigateur ne puisse commencer à afficher la page. En effet, la connexion est effectivement inactive pendant le temps que le serveur met à préparer la réponse.
Les hints précoces sont un code d'état HTTP (103 Early Hints
) utilisé pour envoyer une réponse HTTP préliminaire avant une réponse finale. Cela permet à un serveur d'envoyer des indices au navigateur concernant les sous-ressources critiques (par exemple, les feuilles de style de la page, le code JavaScript critique) ou les origines qui seront probablement utilisées par la page, pendant que le serveur génère la ressource principale. Le navigateur peut utiliser ces indices pour préparer les connexions et demander des sous-ressources, en attendant la ressource principale. En d'autres termes, les premiers indices aident le navigateur à tirer parti de ce "temps de réflexion du serveur" en effectuant une partie du travail à l'avance, ce qui accélère le chargement des pages.
Dans certains cas, l'amélioration des performances de la Largest Contentful Paint peut aller de plusieurs centaines de millisecondes, comme l'ont observé Shopify et Cloudflare, à une seconde de plus, comme le montre cette comparaison avant/après:
Utiliser les premiers indices
La première étape pour profiter des premiers indices consiste à identifier les principales pages de destination, c'est-à-dire les pages sur lesquelles vos utilisateurs commencent généralement lorsqu'ils visitent votre site Web. Il peut s'agir de la page d'accueil ou de pages de fiches produit populaires si vous recevez de nombreux utilisateurs provenant d'autres sites Web. Ces points d'entrée sont plus importants que les autres pages, car l'utilité des premiers indices diminue à mesure que l'utilisateur navigue sur votre site Web (c'est-à-dire que le navigateur est plus susceptible de disposer de toutes les sous-ressources dont il a besoin lors de la deuxième ou troisième navigation ultérieure). Il est également toujours judicieux de faire bonne impression dès le départ.
Maintenant que vous disposez de cette liste hiérarchisée des pages de destination, l'étape suivante consiste à identifier les origines ou les sous-ressources qui pourraient être des bons candidats pour les indices preconnect
ou preload
. Il s'agit généralement des origines et des sous-ressources qui contribuent le plus aux métriques utilisateur clés telles que Largest Contentful Paint (Plus grande peinture avec contenu) ou First Contentful Paint (Premier contenu peint). Plus concrètement, recherchez des sous-ressources bloquant le rendu, telles que des scripts JavaScript synchrones, des feuilles de style ou même des polices Web. De même, recherchez les origines qui hébergent des sous-ressources qui contribuent beaucoup aux métriques utilisateur clés.
Notez également que si vos ressources principales utilisent déjà preconnect
ou preload
, vous pouvez envisager ces origines ou ressources parmi les candidats pour les premiers indices. Pour en savoir plus, consultez comment optimiser le LCP. Toutefois, copier naïvement les directives preconnect
et preload
du code HTML vers les premiers indices n'est pas forcément optimal.
Lorsque vous les utilisez en HTML, vous devez généralement preconnect
ou preload
des ressources que le lecteur de préchargement ne détectera pas dans le code HTML (par exemple, des polices ou des images de fond qui seraient découvertes plus tard). Pour les premiers indices, vous ne disposez pas du code HTML. Vous pouvez donc preconnect
des domaines critiques ou preload
des ressources critiques qui auraient été découvertes plus tôt dans le code HTML (par exemple, en préchargeant main.css
ou app.js
). De plus, tous les navigateurs ne sont pas compatibles avec preload
pour les premiers indices. Consultez la section Compatibilité avec les navigateurs.
La deuxième étape consiste à minimiser le risque d'utiliser des indices précoces sur des ressources ou des origines qui pourraient être obsolètes ou qui ne sont plus utilisées par la ressource principale. Par exemple, les ressources fréquemment mises à jour et versionnées (example.com/css/main.fa231e9c.css
, par exemple) ne sont pas forcément le meilleur choix. Notez que ce problème n'est pas spécifique aux premiers indices. Il s'applique à tous les preload
ou preconnect
, où qu'ils se trouvent. Il s'agit du type de détail le mieux géré par l'automatisation ou la création de modèles (par exemple, un processus manuel est plus susceptible de générer des URL de hachage ou de version non concordantes entre preload
et la balise HTML réelle qui utilise la ressource).
Prenons l'exemple suivant:
GET /main.html
Host: example.com
User-Agent: [....] Chrome/103.0.0.0 [...]
Le serveur prédit que main.abcd100.css
sera nécessaire et suggère de le précharger à l'aide d'Early Hints:
103 Early Hints
Link: </main.abcd100.css>; rel=preload; as=style
[...]
Quelques instants plus tard, la page Web, y compris le CSS associé, est diffusée. Malheureusement, cette ressource CSS est fréquemment mise à jour, et la ressource principale est déjà cinq versions en avance (abcd105
) sur la ressource CSS prévue (abcd100
).
200 OK
[...]
<HTML>
<head>
<title>Example</title>
<link rel="stylesheet" href="/main.abcd105.css">
En général, visez des ressources et des origines assez stables, et largement indépendantes du résultat de la ressource principale. Si nécessaire, vous pouvez diviser vos ressources clés en deux: une partie stable conçue pour être utilisée avec les premiers indices et une partie plus dynamique à extraire une fois que le navigateur a reçu la ressource principale:
<HTML>
<head>
<title>Example</title>
<link rel="stylesheet" href="/main.css">
<link rel="stylesheet" href="/experimental.3eab3290.css">
Enfin, côté serveur, recherchez les requêtes de ressources principales envoyées par les navigateurs connus pour prendre en charge les premiers indices, et répondez immédiatement avec 103 premiers indices. Dans la réponse 103, incluez les indications de préconnexion et de préchargement pertinentes. Une fois la ressource principale prête, envoyez la réponse habituelle (par exemple, 200 OK en cas de réussite). Pour assurer la rétrocompatibilité, il est recommandé d'inclure également des en-têtes HTTP Link
dans la réponse finale, en ajoutant peut-être des ressources critiques qui sont apparues lors de la génération de la ressource principale (par exemple, la partie dynamique d'une ressource clé si vous avez suivi la suggestion "Diviser en deux"). Voici à quoi cela ressemble:
GET /main.html
Host: example.com
User-Agent: [....] Chrome/103.0.0.0 [...]
103 Early Hints
Link: <https://fonts.google.com>; rel=preconnect
Link: </main.css>; rel=preload; as=style
Link: </common.js>; rel=preload; as=script
Quelques instants plus tard:
200 OK
Content-Length: 7531
Content-Type: text/html; charset=UTF-8
Content-encoding: br
Link: <https://fonts.google.com>; rel=preconnect
Link: </main.css>; rel=preload; as=style
Link: </common.js>; rel=preload; as=script
Link: </experimental.3eab3290.css>; rel=preload; as=style
<HTML>
<head>
<title>Example</title>
<link rel="stylesheet" href="/main.css">
<link rel="stylesheet" href="/experimental.3eab3290.css">
<script src="/common.js"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
Prise en charge des navigateurs
Bien que les 103 premiers indices soient compatibles avec tous les principaux navigateurs, les directives pouvant être envoyées dans un premier indice varient selon le navigateur:
Compatibilité avec la préconnexion:
Navigateurs pris en charge
Compatibilité avec le préchargement:
Navigateurs pris en charge
Chrome DevTools est également compatible avec les hints précoces de la version 103, et les en-têtes Link
peuvent être consultés dans les ressources de document:
Pour utiliser les ressources Early Hints, la case Disable cache
ne doit pas être cochée dans DevTools, car Early Hints utilise le cache du navigateur. Pour les ressources préchargées, l'initiateur s'affiche sous la forme early-hints
et la taille sous la forme (Disk cache)
:
Un certificat approuvé est également nécessaire pour les tests HTTPS.
Firefox (à partir de la version 126) n'est pas compatible avec les 103 premiers indices explicites dans DevTools, mais les ressources chargées à l'aide de premiers indices n'affichent pas d'informations d'en-tête HTTP, ce qui est un indicateur qu'elles ont été chargées via des premiers indices.
Support serveur
Voici un bref récapitulatif du niveau de compatibilité des premiers indices avec les logiciels de serveur HTTP open source populaires:
- Apache:compatible avec mod_http2.
- H2O:compatible.
- NGINX:module expérimental.
- Node:compatible depuis la version 18.11.0 pour http et http2
Activer les premiers indices plus facilement
Si vous utilisez l'un des CDN ou plates-formes suivants, vous n'aurez peut-être pas besoin d'implémenter manuellement les premiers indices. Consultez la documentation en ligne de votre fournisseur de solutions pour savoir s'il est compatible avec les premiers indices, ou consultez la liste non exhaustive ci-dessous:
Éviter les problèmes pour les clients qui ne sont pas compatibles avec les premiers indices
Les réponses HTTP informatives de la plage 100 font partie de la norme HTTP, mais certains clients ou bots plus anciens peuvent avoir du mal à les gérer, car avant le lancement des premiers indices 103, elles étaient rarement utilisées pour la navigation Web générale.
L'émission de 103 hints précoces uniquement en réponse aux clients qui envoient un en-tête de requête HTTP sec-fetch-mode: navigate
doit garantir que ces hints ne sont envoyés que pour les clients plus récents qui savent attendre la réponse ultérieure. De plus, comme les premiers indices ne sont compatibles qu'avec les requêtes de navigation (voir les limites actuelles), vous évitez d'en envoyer inutilement sur d'autres requêtes.
De plus, il est recommandé de n'envoyer les premiers indices que via des connexions HTTP/2 ou HTTP/3, et la plupart des navigateurs ne les acceptent que via ces protocoles.
Modèle avancé
Si vous avez appliqué pleinement les premiers indices à vos principales pages de destination et que vous recherchez d'autres opportunités, le modèle avancé suivant peut vous intéresser.
Pour les visiteurs qui effectuent leur n-ième requête de page dans le cadre d'un parcours utilisateur typique, vous pouvez adapter la réponse des premiers indices aux contenus situés plus bas et plus loin dans la page. En d'autres termes, vous pouvez utiliser des premiers indices sur des ressources de priorité inférieure. Cela peut sembler contre-intuitif, car nous vous avons recommandé de vous concentrer sur les sous-ressources ou origines bloquant le rendu de priorité élevée. Toutefois, au bout d'un certain temps, il est très probable que le navigateur du visiteur dispose déjà de toutes les ressources critiques. À partir de là, il peut être judicieux de vous concentrer sur les ressources de moindre priorité. Par exemple, vous pouvez utiliser des indices précoces pour charger des images de produits ou des fichiers JS/CSS supplémentaires qui ne sont nécessaires que pour des interactions utilisateur moins courantes.
Limites actuelles
Voici les limites des premiers indices tels qu'implémentés dans Chrome:
- Disponible uniquement pour les requêtes de navigation (c'est-à-dire la ressource principale du document de niveau supérieur).
- Compatible uniquement avec
preconnect
etpreload
(prefetch
n'est pas compatible). - Si des hints précoces sont suivis d'une redirection inter-origine dans la réponse finale, Chrome abandonne les ressources et les connexions qu'il a obtenues à l'aide de hints précoces.
- Les ressources préchargées à l'aide d'Early Hints sont stockées dans le cache HTTP et récupérées par la page ultérieurement. Par conséquent, seules les ressources pouvant être mises en cache peuvent être préchargées à l'aide d'Early Hints, sinon la ressource sera récupérée deux fois (une fois par Early Hints et une fois par le document). Dans Chrome, le cache HTTP est désactivé pour les certificats HTTPS non approuvés (même si vous continuez à charger la page).
- Le préchargement d'images responsives (à l'aide de
imagesrcset
,imagesizes
oumedia
) n'est pas compatible avec les en-têtes HTTP<link>
, car le viewport n'est pas défini tant que le document n'est pas créé. Cela signifie que les 103 indices précoces ne peuvent pas être utilisés pour précharger des images responsives et qu'ils peuvent charger l'image incorrecte lorsqu'ils sont utilisés à cette fin. Suivez cette discussion sur les propositions pour mieux gérer ce problème.
D'autres navigateurs présentent des limites similaires et, comme indiqué précédemment, certains limitent davantage les 103 indices précoces à preconnect
uniquement.
Étape suivante
En fonction de l'intérêt de la communauté, nous pouvons compléter notre implémentation des premiers indices avec les fonctionnalités suivantes:
- Remarques précoces pour les ressources non enregistrables à l'aide du cache mémoire plutôt que du cache HTTP.
- Requêtes d'indices anticipés envoyées sur les requêtes de sous-ressources.
- Requêtes de ressources principales de l'iFrame envoyées avec des indices précoces.
- Prise en charge du préchargement dans les premiers indices.
Nous vous invitons à nous faire part de vos commentaires sur les aspects à prioriser et sur la façon d'améliorer davantage les premiers indices.
Relation avec H2/Push
Si vous connaissez la fonctionnalité HTTP2/Push obsolète, vous vous demandez peut-être en quoi les premiers indices sont différents. Alors que les premiers indices nécessitent un aller-retour pour que le navigateur commence à extraire les sous-ressources critiques, avec HTTP2/Push, le serveur peut commencer à transférer des sous-ressources en même temps que la réponse. Bien que cela puisse sembler incroyable, cela a entraîné un inconvénient structurel majeur: avec HTTP2/Push, il était extrêmement difficile d'éviter de transférer des sous-ressources que le navigateur possédait déjà. Cet effet de "sur-poussée" a entraîné une utilisation moins efficace de la bande passante réseau, ce qui a considérablement limité les avantages en termes de performances. Globalement, les données Chrome ont montré que HTTP2/Push avait un impact négatif sur les performances sur le Web.
En revanche, les premiers indices sont plus performants en pratique, car ils combinent la possibilité d'envoyer une réponse préliminaire avec des indices qui laissent le navigateur chargé de récupérer ou de se connecter à ce dont il a réellement besoin. Bien que les premiers indices ne couvrent pas tous les cas d'utilisation que HTTP2/Push pourrait traiter en théorie, nous pensons qu'ils constituent une solution plus pratique pour accélérer les navigations.
Image miniature par Pierre Bamin.