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 de plus en plus sophistiqués au fil du temps. Ainsi, il n'est pas rare qu'un serveur effectue des tâches complexes (par exemple, l'accès à des bases de données ou aux CDN accédant au serveur d'origine) pour produire le code HTML de la page demandée. Malheureusement, cette "réflexion du serveur" entraîne une latence supplémentaire avant que le navigateur ne commence à 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 intervalle de temps de réflexion du serveur de 200 ms entre le chargement de la page et celui des autres ressources
Sans les premiers indices: tout est bloqué sur le serveur pour déterminer le mode de réponse pour la ressource principale.

Les premiers indices sont un code d'état HTTP (103 Early Hints) qui permet d'envoyer une réponse HTTP préliminaire avant la réponse finale. Cela permet à un serveur d'envoyer au navigateur des indications sur les sous-ressources critiques (par exemple, les feuilles de style de la page, le code JavaScript critique) ou les origines susceptibles d'être utilisées par la page, tandis que le serveur est occupé à générer 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 sur le serveur" en effectuant un 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 Largest Contentful Paint peut aller de quelques centaines de millisecondes, comme observé par Shopify et par Cloudflare, et jusqu'à une seconde plus vite, comme le montre la comparaison avant et après:

Comparaison de deux sites
Comparaison avant/après des premiers indices sur un site Web test effectué à l'aide de WebPageTest (Moto G4 – DSL)

Utiliser les premiers indices

Pour tirer parti des premiers indices, la première étape consiste à identifier les principales pages de destination, c'est-à-dire les pages sur lesquelles les utilisateurs commencent généralement lorsqu'ils visitent votre site Web. Il peut s'agir de la page d'accueil ou des pages de fiches produit populaires si de nombreux utilisateurs proviennent d'autres sites Web. La raison pour laquelle ces points d'entrée sont plus importants que les autres pages est que l'utilité des premiers indices diminue à mesure que l'utilisateur parcourt votre site Web. En d'autres termes, 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. C'est aussi une bonne idée de faire tout de suite bonne impression !

Maintenant que vous disposez de cette liste de pages de destination classées par ordre de priorité, l'étape suivante consiste à identifier les origines ou sous-ressources qui se prêtent bien aux indications preconnect ou preload. En règle générale, il s'agit des origines et sous-ressources qui contribuent le plus aux métriques utilisateur clés, telles que Largest Contentful Paint ou First Contentful Paint. Plus concrètement, recherchez les sous-ressources qui bloquent l'affichage, telles que le code JavaScript synchrone, les feuilles de style ou même les polices Web. De même, recherchez les origines qui hébergent des sous-ressources qui contribuent grandement 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 propositions pour les premiers indices. Pour en savoir plus, découvrez 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 dans du code HTML, il est généralement préférable d'preconnect ou de preload pour les ressources que l'outil Preload Scanner ne détectera pas dans le code HTML (polices ou images de fond, par exemple, qui seraient autrement découverts tard). Pour les premiers indices, vous ne disposez pas du code HTML. Nous vous conseillons donc d'utiliser plutôt preconnect vers les domaines critiques ou preload ressources critiques qui seraient autrement découvertes tôt dans le code HTML (par exemple, le préchargement de main.css ou app.js). De plus, tous les navigateurs ne sont pas compatibles avec preload pour les premiers indices. Consultez 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, quel que soit leur emplacement. Il s'agit du type de détail le mieux géré avec l'automatisation ou la création de modèles (par exemple, un processus manuel est plus susceptible de générer des incohérences au niveau des URL de hachage ou de version entre preload et la balise HTML 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 a déjà cinq versions d'avance (abcd105) sur la ressource CSS prédite (abcd100).

200 OK
[...]
<HTML>
<head>
   <title>Example</title>
   <link rel="stylesheet" href="/main.abcd105.css">

En règle générale, privilégiez les ressources et les origines qui sont assez stables, et qui sont en grande partie indépendantes du résultat de la ressource principale. Si nécessaire, vous pouvez envisager de 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 restant à extraire une fois la ressource principale reçue par le navigateur:

<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 conseils de préconnexion et de préchargement pertinents. Une fois que la ressource principale est prête, effectuez un suivi avec 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 l'option 103 Early Hints soit compatible avec tous les principaux navigateurs, les directives qui peuvent être envoyées avec cette fonctionnalité diffèrent selon les navigateurs:

Assistance de préconnexion:

Navigateurs pris en charge

  • 103
  • 103
  • 120
  • 17

Prise en charge du préchargement:

Navigateurs pris en charge

  • 103
  • 103
  • 123
  • x

Les outils pour les développeurs Chrome proposent également 103 premières suggestions, et les en-têtes Link sont visibles dans les ressources du document:

Panneau &quot;Network&quot; (Réseau) affichant les en-têtes des premiers indices Les en-têtes
Early Hints Link s'affichent dans les outils pour les développeurs Chrome.

Notez que pour utiliser les ressources d'alertes précoces, la case Disable cache ne doit pas être cochée dans les outils de développement, car cette fonctionnalité utilise le cache du navigateur. Pour les ressources préchargées, le champ initiator indique early-hints et la taille est (Disk cache):

Panneau &quot;Network&quot; (Réseau) affichant les déclencheurs d&#39;indicateurs précoces
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) ne prend pas explicitement en charge les premiers indices 103 dans les outils de développement, mais les ressources chargées à l'aide des premiers indices n'affichent pas les informations d'en-tête HTTP, qui font partie des indicateurs de chargement.

Support serveur

Voici un bref récapitulatif du niveau de prise en charge des premiers indices parmi les logiciels Open Source populaires de serveur HTTP:

Activez facilement les premiers indices

Si vous utilisez l'une des plates-formes ou l'un des CDN 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 disponible ici:

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.

N'émettre de 103 alertes précoces qu'en réponse aux clients qui envoient un en-tête de requête HTTP sec-fetch-mode: navigate doit garantir que ces indices ne sont envoyés qu'aux nouveaux clients qui comprennent qu'ils doivent attendre la réponse suivante. De plus, comme les premiers indices ne sont compatibles qu'avec les requêtes de navigation (voir les limites actuelles), cela présente l'avantage supplémentaire d'éviter de les envoyer inutilement à d'autres requêtes.

En outre, il est recommandé d'envoyer les premiers indices uniquement via des connexions HTTP/2 ou HTTP/3, et la plupart des navigateurs ne les accepteront que via ces protocoles.

Modèle avancé

Si vous avez entièrement appliqué les indications précoces à 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 se trouvent sur leur nth page dans le cadre d'un parcours utilisateur standard, vous pouvez adapter la réponse des premiers indices au contenu situé plus bas et plus loin sur la page. En d'autres termes, vous pouvez utiliser les premiers indices sur les ressources les moins prioritaires. Cela peut sembler contre-intuitif, étant donné que nous recommandons de se concentrer sur les sous-ressources ou les origines à priorité élevée qui bloquent l'affichage. Toutefois, au moment où un visiteur a utilisé la navigation pendant un certain temps, il est très probable que son navigateur dispose déjà de toutes les ressources essentielles. À partir de ce moment, il peut être judicieux de recentrer votre attention sur les ressources moins prioritaires. Par exemple, vous pouvez utiliser les premiers indices pour charger les images des produits, ou utiliser 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é).
  • S'ils sont suivis d'une redirection multi-origine sur la réponse finale, Chrome supprimera les ressources et les connexions obtenues à l'aide des premiers indices.
  • Les ressources préchargées à l'aide des premiers indices sont stockées dans le cache HTTP, puis récupérées ultérieurement par la page. Par conséquent, seules les ressources pouvant être mises en cache peuvent être préchargées à l'aide des premiers indices, sans quoi la ressource sera récupérée une fois (une fois par les premiers indices, puis une seconde 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).

D'autres navigateurs présentent des limites similaires et, comme indiqué précédemment, certains limitent encore les 103 premières suggestions à preconnect uniquement.

Étape suivante

En fonction de l'intérêt de la communauté, nous pouvons étendre notre implémentation des premiers indices avec les fonctionnalités suivantes:

  • Premières astuces pour les ressources ne pouvant pas être mises en cache qui utilisent le cache de la mémoire plutôt que le cache HTTP.
  • Indices précoces envoyés pour les demandes de sous-ressources.
  • Indices précoces envoyés en réponse aux demandes de ressources principales de l'iFrame.
  • Prise en charge du préchargement dans les premiers indices.

N'hésitez pas à nous faire part de vos commentaires concernant les aspects à prioriser et la façon d'améliorer encore les premiers indices.

Relation avec H2/Push

Si vous connaissez la fonctionnalité HTTP2/Push obsolète, vous vous demandez peut-être en quoi cette fonctionnalité diffère. Alors qu'avec les premiers indices, un aller-retour est nécessaire pour que le navigateur commence à récupérer les sous-ressources critiques, mais avec HTTP2/Push, le serveur peut commencer à transmettre 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 « trop poussée » a conduit à une utilisation moins efficace de la bande passante réseau, ce qui a considérablement entravé les gains de performances. Dans l'ensemble, les données de Chrome ont montré que le protocole HTTP2/Push a un impact net sur les performances sur le Web.

En revanche, dans la pratique, les premiers indices offrent de meilleures performances, car ils permettent d'envoyer une réponse préliminaire avec des indications qui laissent le navigateur se charger de récupérer ou de se connecter à ce dont il a réellement besoin. Bien que cette fonctionnalité ne couvre pas tous les cas d'utilisation que le protocole HTTP2/Push pourrait traiter en théorie, nous pensons qu'il s'agit d'une solution plus pratique pour accélérer les navigations.

Vignette de Pierre Bamin.