Chargement des pages plus rapide grâce à l'utilisation du temps de réflexion du serveur avec les premiers conseils

Découvrez comment votre serveur peut envoyer au navigateur des indications sur 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 reste inactive aussi longtemps qu'il faut au serveur pour préparer la réponse.

Image montrant un écart de temps de réflexion de 200 ms entre le chargement de la page et le chargement d'autres ressources.
Sans Early Hints : tout est bloqué sur le serveur, qui détermine comment répondre pour la ressource principale.

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 suggestions 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.

Image montrant comment la fonctionnalité d'indications précoces permet à la page d'envoyer une réponse partielle
Avec les premiers indices: le serveur peut fournir une réponse partielle avec des indications de ressources pendant qu'il détermine la réponse finale

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 :

Comparaison de deux sites.
Comparaison avant/après des premiers indices sur un site Web de test effectuée avec WebPageTest (Moto G4 – DSL)

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 !

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 (Largest Contentful Paint) ou First Contentful Paint (First Contentful Paint). 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 de les inclure parmi les candidats aux premiers indices. Pour en savoir plus, consultez comment optimiser le LCP. Toutefois, la copie naïve des instructions preconnect et preload du code HTML vers les premiers indices peut ne pas être optimale.

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 à réduire le risque d'utilisation des premiers indices sur des ressources ou des origines susceptibles d'être obsolètes, ou de ne plus être utilisées par la ressource principale. Par exemple, les ressources dont la mise à jour et la gestion des versions sont fréquentes (example.com/css/main.fa231e9c.css, par exemple) ne sont peut-être pas 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).

À titre d'exemple, prenons le flux 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 des premiers indices:

103 Early Hints
Link: </main.abcd100.css>; rel=preload; as=style
[...]

Quelques instants plus tard, la page Web et le CSS associé sont diffusés. 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 principales demandes de ressources envoyées par les navigateurs connus pour être compatibles avec les premiers indices, et répondez immédiatement avec l'erreur 103. 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 les en-têtes HTTP Link dans la réponse finale, voire d'y ajouter des ressources critiques qui sont devenues évidentes lors de la génération de la ressource principale (par exemple, la partie dynamique d'une ressource de clé si vous avez suivi la suggestion de division en deux). Voici à quoi cela ressemblerait:

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

  • Chrome: 103.
  • Edge: 103.
  • Firefox : 120.
  • Safari : 17.

Compatibilité avec le préchargement :

Navigateurs pris en charge

  • Chrome: 103.
  • Edge : 103.
  • Firefox : 123.
  • Safari : non compatible.

Chrome DevTools est également compatible avec les hints précoces de la version 103. Les en-têtes Link sont visibles dans les ressources de document :

Volet &quot;Network&quot; (Réseau) affichant les en-têtes des premiers indices
Les en-têtes Link des premiers indices sont affichés dans les outils pour les développeurs Chrome.

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) :

Panneau &quot;Network&quot; (Réseau) affichant les initiateurs d&#39;Early Hints
Les ressources avec indication précoce ont un déclencheur early-hints et sont chargées à partir du cache disque.

Cela nécessite également un certificat de confiance 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 ces indices ne montrent pas d'informations d'en-tête HTTP, ce qui est un indicateur qu'elles ont été chargées via ces indices.

Support serveur

Voici un bref récapitulatif du niveau de compatibilité de la fonctionnalité Indices précoces parmi les logiciels Open Source les plus populaires de serveur HTTP:

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 :

Comment éviter les problèmes pour les clients non compatibles avec cette fonctionnalité

Les réponses HTTP d'information de la plage 100 font partie de la norme HTTP, mais certains robots ou clients plus anciens peuvent rencontrer des difficultés, car avant le lancement des 103 premiers indices, elles étaient rarement utilisées pour la navigation générale sur le Web.

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 comprennent qu'ils doivent 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, étant donné que nous recommandons de se concentrer sur les origines ou sous-ressources à priorité élevée qui bloquent l'affichage. 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 les premiers indices pour charger les images des produits, ou des fichiers JS/CSS supplémentaires qui ne sont nécessaires que pour les interactions utilisateur moins courantes.

Limites actuelles

Voici les limites des premiers indices mis en œuvre dans Chrome:

  • Disponible uniquement pour les requêtes de navigation (c'est-à-dire la ressource principale du document de niveau supérieur).
  • Accepte uniquement preconnect et preload (c'est-à-dire que prefetch n'est pas accepté).
  • 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 ou media) 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 103 Early Hints ne peut pas être utilisé pour précharger les images responsives. Dans ce cas, il est possible que l'image ne soit pas chargée correctement. 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 premières suggestions à 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'indications anticipées 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 indiquer les aspects à prioriser et à nous faire part de vos suggestions pour améliorer 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 à pousser des sous-ressources en même temps que la réponse. Bien que cela puisse sembler incroyable, cela a engendré un inconvénient structurel important: avec HTTP2/Push, il était extrêmement difficile d'éviter de transférer des sous-ressources dont le navigateur disposait 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.

Vignette de Pierre Bamin.