Early Hints (HTTP 103) : annoncer les ressources critiques pendant que le serveur réfléchit

Avec le code 103, le serveur ou le CDN indique au navigateur quelles ressources télécharger pendant que la page est encore en préparation : comment cela fonctionne, quand cela rapporte, comment l’utiliser avec WordPress et quoi annoncer.

Un serveur dont le code 103 est mis en évidence, qui envoie en avance le CSS, les polices et l’image hero, tandis que la réponse 200 arrive plus tard

Chaque fois qu’un navigateur demande une page, il y a un moment où il ne se passe rien. La requête est partie, le serveur la traite, interroge la base de données, exécute le code de l’application, construit le HTML. Le navigateur attend. Ce n’est qu’en recevant la réponse qu’il découvre les feuilles de style, les polices et les images dont il a besoin pour afficher la page, et qu’il commence à les télécharger. Sur un site doté d’un cache de page, cet intervalle dure quelques dizaines de millisecondes ; sur les pages dynamiques, comme le panier, les espaces membres ou les résultats de recherche, il peut durer des centaines de millisecondes, parfois plus d’une seconde.

Early Hints, le code d’état HTTP 103, existe pour exploiter ce temps mort. Le serveur, ou le CDN placé devant lui, peut envoyer immédiatement une réponse préliminaire qui dit au navigateur : pendant que je prépare la page, commence à télécharger ces ressources, car tu en auras besoin. Quand la vraie réponse arrive, les ressources critiques sont déjà en route ou déjà téléchargées.

Comment fonctionne le code 103

Les codes d’état de la famille 1xx sont des réponses informatives : ils ne concluent pas la requête, mais peuvent précéder sa réponse finale. La réponse 103 Early Hints contient un ou plusieurs en-têtes Link, avec la même syntaxe que celle utilisée pour preload et preconnect. Une séquence typique ressemble à ceci :

HTTP/2 103
link: </wp-content/themes/tema/style.css>; rel=preload; as=style
link: </wp-content/themes/tema/fonts/plex.woff2>; rel=preload; as=font; crossorigin
link: <https://cdn.example.com>; rel=preconnect

HTTP/2 200
content-type: text/html; charset=UTF-8
link: </wp-content/themes/tema/style.css>; rel=preload; as=style

<!doctype html>…

Après avoir reçu le 103, le navigateur commence aussitôt à télécharger la feuille de style et la police, et ouvre la connexion vers le domaine indiqué. Puis il continue d’attendre la réponse 200, qui arrive quand le serveur a terminé. À ce moment-là, les ressources annoncées sont déjà disponibles ou bien avancées, et le navigateur peut construire et afficher la page sans la chaîne d’attentes habituelle.

Comparaison de deux chargements de page : sans Early Hints, le navigateur attend que le serveur génère la page, reçoit le HTML et ne télécharge qu’ensuite le CSS, les polices et l’image hero, avec un LCP de 1,45 seconde ; avec le 103, le CSS, les polices et l’image sont téléchargés pendant que le serveur travaille et le LCP tombe à 0,9 seconde
Avec Early Hints, le temps que le serveur passe à générer la page devient du temps utile pour le navigateur.

Pourquoi le preload dans le HTML ne suffit pas

Un <link rel="preload"> dans l’en-tête du HTML a le même objectif, mais une limite évidente : le navigateur ne le lit que lorsqu’il reçoit le HTML, donc après que le serveur a terminé son travail. Le preload accélère la découverte des ressources par rapport au moment où elles seraient trouvées dans le CSS ou plus bas dans le document, mais il ne peut pas l’avancer par rapport à la réponse elle-même. Early Hints déplace ce moment au début de la requête, avant que le serveur ait produit le moindre octet de la page.

Il a été proposé comme successeur de HTTP/2 Server Push, le mécanisme par lequel le serveur pouvait envoyer des ressources au navigateur sans qu’il les ait demandées. Le push s’est révélé difficile à bien utiliser, car le serveur ne savait pas quelles ressources le navigateur avait déjà dans son cache et finissait par envoyer des données inutiles ; Chrome l’a supprimé en 2022. Early Hints laisse au contraire la décision au navigateur : le serveur suggère, et le navigateur ne télécharge que ce qu’il n’a pas déjà, grâce à son propre cache.

Quand cela rapporte vraiment

Le bénéfice d’Early Hints est proportionnel au temps d’attente du serveur. Si une page arrive du cache avec un TTFB de 40 millisecondes, il n’y a presque pas de temps mort à exploiter, et le gain est négligeable. Si une page met 600 millisecondes à être traitée, le navigateur peut les employer à télécharger des feuilles de style, des polices et même l’image principale, et le gain sur le LCP peut atteindre plusieurs centaines de millisecondes.

Les cas les plus favorables sont donc les pages qui ne peuvent pas être mises en cache : panier et paiement d’un site e-commerce, espaces membres, pages personnalisées, résultats de recherche interne, pages avec paramètres. Ce sont aussi des pages importantes pour l’activité, et souvent les plus lentes du site. Pour les pages déjà servies depuis le cache, Early Hints est une petite amélioration ; pour les pages dynamiques, ce peut être l’une des rares interventions possibles sans réécrire l’application.

Un exemple concret

Imaginons la page panier d’une boutique en ligne, qui ne peut pas être mise en cache et que le serveur génère en 700 millisecondes environ, entre session, calcul des prix, livraison et produits recommandés. Sans Early Hints, le navigateur reste inactif pendant tout ce temps ; puis il reçoit le HTML, découvre la feuille de style principale, la télécharge en 150 millisecondes sur un réseau mobile, découvre la police, la télécharge, et enfin affiche. Le LCP arrive après plus d’une seconde, alors que le texte et les miniatures des produits sont très légers.

Avec un 103 qui annonce la feuille de style et la police, le navigateur les télécharge pendant les 700 millisecondes de traitement. Quand le HTML arrive, il a déjà tout ce qu’il lui faut pour afficher, et le LCP se rapproche beaucoup du TTFB. Le serveur n’est pas devenu plus rapide, mais la page apparaît quelques centaines de millisecondes plus tôt, exactement au point du parcours d’achat où l’utilisateur est le plus proche de conclure, comme nous l’avons vu à propos des Core Web Vitals pour WooCommerce.

Qui peut l’envoyer : d’abord le CDN

Envoyer un 103, c’est répondre avant d’avoir la réponse, et ce n’est pas trivial pour beaucoup d’applications. PHP, par exemple, dans la configuration traditionnelle avec PHP-FPM, n’a pas de moyen simple d’envoyer une réponse informative puis de continuer à traiter la page. Pour cette raison, la manière la plus courante d’utiliser Early Hints passe par le CDN.

Certains CDN, comme Cloudflare, adoptent une approche élégante : ils observent les en-têtes Link avec rel=preload ou rel=preconnect présents dans les réponses 200 de l’origine, les mémorisent pour cette URL et, lors des requêtes suivantes, les envoient immédiatement au navigateur sous forme de 103 tout en transmettant la requête à l’origine. Le site n’a qu’à inclure les en-têtes Link dans ses propres réponses et à activer la fonction dans le tableau de bord du CDN.

Diagramme de séquence entre navigateur, CDN et serveur d’origine : le navigateur demande la page, le CDN transmet la requête à l’origine et répond entre-temps au navigateur par un 103 Early Hints ; le navigateur télécharge le CSS et les polices pendant que l’origine traite avec PHP et la base de données ; enfin la réponse 200 avec le HTML arrive de l’origine au navigateur via le CDN
Le CDN envoie le 103 à partir des réponses précédentes, sans attendre l’origine.

Certains serveurs web prennent aussi en charge l’envoi d’Early Hints : Apache, avec le module HTTP/2, peut transformer des en-têtes Link configurés en 103, et d’autres serveurs et environnements applicatifs modernes proposent des fonctions dédiées. La prise en charge reste toutefois moins uniforme que sur les CDN, et doit être vérifiée au cas par cas.

Le cas de WordPress

Sur WordPress, l’approche la plus pratique consiste à ajouter des en-têtes Link aux réponses HTML et à laisser le CDN les envoyer en avance. La feuille de style principale du thème et la police la plus utilisée au-dessus de la ligne de flottaison sont les candidates idéales, car elles sont identiques sur chaque page :

add_action(
	'send_headers',
	function () {
		if ( is_admin() ) {
			return;
		}
		$tema = get_template_directory_uri();
		header( "Link: <{$tema}/style.css>; rel=preload; as=style", false );
		header( "Link: <{$tema}/fonts/plex.woff2>; rel=preload; as=font; crossorigin", false );
	}
);

Les URL doivent correspondre exactement à celles utilisées dans la page, y compris les éventuels paramètres de version comme ?ver=1.2 : si elles diffèrent, le navigateur télécharge deux fois la même ressource. Pour cette raison, il est préférable de générer les en-têtes avec les mêmes fonctions que celles qu’utilise le thème pour enregistrer les styles, ou de s’appuyer sur des plugins d’optimisation qui les produisent automatiquement et de façon cohérente.

Ce qu’il faut annoncer et ce qu’il ne faut pas annoncer

Early Hints est un outil à utiliser avec parcimonie. Chaque ressource annoncée entre en concurrence avec les autres pour la bande passante, et annoncer trop revient à ne rien prioriser. Quelques règles pratiques :

  • Le CSS critique, toujours. La feuille de style qui bloque le rendu est le meilleur candidat : sans elle, la page ne peut pas être affichée.
  • Une ou deux polices. Celles utilisées dans le texte au-dessus de la ligne de flottaison, au format WOFF2, de préférence déjà réduites par du subsetting.
  • Un preconnect vers les domaines critiques. Le CDN d’images ou un domaine tiers indispensable au premier affichage. Un preconnect coûte peu et épargne les allers-retours d’ouverture de la connexion.
  • L’image LCP seulement si elle est toujours la même. Une image de couverture qui change d’une page à l’autre ne peut pas être annoncée par un CDN qui mémorise les en-têtes par URL seulement après la première visite ; cela a du sens pour une image fixe, comme celle de la page d’accueil.
  • Aucun script non critique. Avancer le téléchargement d’un JavaScript qui s’exécutera plus tard n’accélère pas le premier affichage et prend de la bande passante à ce qui est nécessaire.

Les erreurs les plus courantes

La première erreur est l’URL qui ne correspond pas. Si l’en-tête annonce style.css et que la page charge style.css?ver=6.8, pour le navigateur ce sont deux ressources différentes : la première est téléchargée puis ignorée, la seconde est demandée à nouveau. Le résultat est pire que de ne pas utiliser Early Hints, car on gaspille de la bande passante au moment le plus délicat du chargement. Les DevTools le signalent par un avertissement concernant une ressource préchargée mais non utilisée en quelques secondes.

La deuxième erreur concerne les polices : précharger une police exige l’attribut crossorigin, même quand la police se trouve sur le même domaine, car les polices sont toujours demandées en mode CORS. Sans lui, le navigateur télécharge la police deux fois. La troisième consiste à annoncer des ressources autres que celles réellement nécessaires, par exemple après une mise à jour du thème qui a changé des noms de fichiers ou des chemins : les en-têtes restent les anciens, et le CDN continue d’annoncer des fichiers que la page n’utilise plus. Après chaque modification structurelle, il vaut donc la peine de revérifier la correspondance entre les ressources annoncées et utilisées.

Enfin, il ne faut pas confondre Early Hints avec un remède aux problèmes du serveur. Si une page met deux secondes à être générée, avancer le CSS et les polices améliore la situation, mais l’utilisateur voit tout de même une page blanche jusqu’à l’arrivée du HTML. Le travail sur le TTFB, avec cache de page, cache d’objets et optimisation des requêtes, reste la priorité ; Early Hints est le complément qui récupère le temps que l’on ne peut pas éliminer.

La prise en charge par les navigateurs

Chrome et Edge prennent en charge Early Hints pour preload et preconnect dans les requêtes de navigation, sur des connexions HTTP/2 et HTTP/3. Firefox le prend en charge dans les versions récentes ; Safari prend en charge preconnect mais, au moment de la rédaction, pas le preload via 103. Les navigateurs qui ne le prennent pas en charge ignorent la réponse informative et attendent la réponse finale, comme toujours : ici aussi, comme pour les Speculation Rules, il s’agit d’une amélioration progressive sans effet négatif pour ceux qui n’en profitent pas.

Comment vérifier

Dans les DevTools de Chrome, les ressources téléchargées grâce à Early Hints affichent un initiateur dédié dans le panneau Network, et la Resource Timing API les signale avec un initiatorType égal à early-hints. C’est le moyen le plus fiable de vérifier que les en-têtes parviennent bien au navigateur et que les URL correspondent à celles qu’utilise la page :

performance.getEntriesByType( 'resource' )
	.filter( ( r ) => r.initiatorType === 'early-hints' )
	.forEach( ( r ) => console.log( r.name, Math.round( r.responseEnd ) ) );

En ligne de commande, curl -I sur une URL servie par le CDN montre les éventuelles réponses 103 avant le 200. Pour mesurer l’effet, comparez le TTFB et le LCP des pages dynamiques avant et après l’activation, avec des données de terrain ou un système de real user monitoring : sur les pages en cache, la différence sera faible, sur les pages dynamiques elle devrait être nette.

En bref

Early Hints permet au serveur, ou plus souvent au CDN, d’indiquer au navigateur quelles ressources critiques télécharger pendant que la page est encore en préparation. Il transforme le temps d’attente du serveur en temps utile, et le bénéfice croît avec la lenteur de la page : modeste pour les pages en cache, significatif pour le panier, le paiement, les espaces membres et les pages personnalisées.

Il s’active avec quelques en-têtes Link bien choisis et un CDN qui les transforme en 103 ; il faut le limiter aux ressources vraiment critiques, avec des URL identiques à celles de la page, et le vérifier avec les DevTools. Il ne remplace ni un cache efficace ni un serveur rapide, mais quand la page ne peut pas être générée plus vite, c’est l’un des meilleurs moyens de faire en sorte que l’attente ne soit pas perdue.

L’ÉTAPE SUIVANTE

Commençons
par votre site.

Parlez-nous du projet, des problèmes que vous constatez et de vos objectifs. Ensemble, nous définirons une intervention sur mesure.

Demander une analyse

Vous mène au formulaire de la page Contact.

MANAGED SERVER S.R.L.info@corewebvitals.fr +39 02 5656 9681

Du lundi au vendredi · 9 h 30 – 19 h 30 (CET)

Vous préférez un formulaire en ligne ?
Contactez-nous sur managedserver.it ↗