Il y a une catégorie de problèmes de performance qui ne te saute jamais aux yeux, parce qu'elle ne casse rien de visible. Le site s'affiche, les boutons marchent, tout semble normal. Et pourtant, en coulisses, une partie de ta page se construit deux fois, scintille une fraction de seconde, ou perd un état au passage. C'est une fuite de rendu côté serveur, et son danger, c'est précisément qu'elle ne crashe pas. Elle coûte sans prévenir.

Le mécanisme tient en une phrase. Quand ton serveur génère un HTML et que le navigateur, en reprenant la main, calcule un résultat différent, les deux ne racontent pas la même histoire. Le navigateur jette alors ce que le serveur avait produit et recommence. Tu paies un double travail, parfois un scintillement visible, parfois une interactivité qui se branche en retard. Voici pourquoi ça arrive, les causes classiques, et comment les traquer.

Quand le serveur et le navigateur ne racontent pas la même histoire

Dans une application moderne, ta page est d'abord rendue sur le serveur, qui envoie un HTML prêt à afficher. C'est rapide et bon pour la première impression, et c'est une grande partie de ce qui rend Next.js efficace pour la conversion. Ensuite, le navigateur reprend ce HTML et l'hydrate, c'est à dire qu'il y rebranche la logique. Pour que ça marche proprement, le navigateur doit calculer exactement le même résultat que le serveur. S'il calcule la même chose, l'hydratation est silencieuse et gratuite.

Mais si le navigateur calcule quelque chose de différent du HTML reçu, il y a désaccord. Le navigateur ne peut pas faire confiance au HTML du serveur, alors il le jette et reconstruit cette partie de zéro côté client. C'est ça, la fuite. Le travail du serveur est perdu, refait par le navigateur, et ton visiteur voit parfois le contenu changer sous ses yeux, un texte qui saute, un bloc qui réapparaît, un bouton qui devient cliquable avec un temps de retard.

Le vrai danger, c'est l'invisibilité du problème. Un crash, tu le vois et tu le corriges. Une fuite d'hydratation, elle, se cache dans un avertissement de console que personne ne lit, pendant qu'elle dégrade la performance et la stabilité à chaque chargement. Elle ne te réveille pas la nuit, elle te saigne lentement.

Reste à savoir d'où viennent ces désaccords. En pratique, ils naissent presque toujours d'un même type de faute, le serveur et le client n'ont pas la même information au moment de calculer.

  • Les valeurs non déterministes. Afficher l'heure courante, une date relative comme "il y a deux minutes", un nombre aléatoire. Le serveur calcule une valeur, le navigateur en calcule une autre une fraction de seconde plus tard. Désaccord garanti.
  • Les API du navigateur lues pendant le rendu. Accéder à la largeur de la fenêtre, au stockage local, à un thème enregistré, directement dans le rendu. Le serveur n'a pas de fenêtre, donc il produit un résultat, et le navigateur en produit un autre une fois la vraie valeur connue.
  • Les différences de locale ou de fuseau. Formater une date ou un nombre selon un fuseau ou une langue qui diffère entre le serveur et le client. Le rendu sort différent des deux côtés, sans que personne l'ait voulu.

Le point commun, c'est que le rendu dépend d'une information qui n'est pas la même sur le serveur et dans le navigateur au moment du calcul. La correction consiste toujours à rendre ce calcul déterministe, ou à le repousser après l'hydratation.

Prends l'exemple le plus banal, un horodatage relatif du type "publié il y a deux minutes". Le serveur calcule ce texte à l'instant où il génère la page. Le navigateur, lui, hydrate quelques centaines de millisecondes plus tard, et calcule "il y a deux minutes et une fraction", soit un texte légèrement différent. Pour le navigateur, c'est un désaccord, donc il jette et refait. Un détail aussi anodin qu'un horodatage déclenche une fuite, à chaque chargement, sur chaque carte qui l'affiche. Multiplie par une liste de vingt éléments, et tu as vingt petites reconstructions silencieuses sur une seule page.

Comparaison avant après : un rendu où serveur et client sont en désaccord et le HTML est jeté, contre un rendu déterministe sans avertissement.
Le serveur et le client en désaccord, valeur non déterministe, API navigateur lue tôt, HTML jeté et refait, contre le rendu déterministe, valeur stable puis mise à jour, API lue après montage, zéro avertissement.

Un avertissement d'hydratation n'est jamais cosmétique

Beaucoup de développeurs voient passer le message "le contenu ne correspond pas au HTML rendu par le serveur" et l'ignorent, parce que la page a l'air de marcher. C'est une erreur de jugement. Cet avertissement n'est pas du bruit, c'est le symptôme d'une partie de ta page qui se reconstruit dans le dos du visiteur.

Je le pose clairement. Un avertissement d'hydratation est un bug de performance à traiter, pas une coquetterie à tolérer. Chaque mismatch est un morceau de travail serveur jeté à la poubelle et refait côté client, sur le fil principal, celui qui devrait répondre aux interactions. Tolérer ces avertissements, c'est accepter de payer un double rendu en permanence pour ne pas avoir à comprendre d'où il vient. Le confort à court terme se paie en lenteur durable.

La checklist pour repérer et corriger la fuite

  1. Ne rends jamais une valeur non déterministe au premier rendu. Heure, date relative, aléatoire. Affiche une valeur stable d'abord, puis mets à jour après l'hydratation, dans un effet côté client.
  2. Ne lis aucune API du navigateur pendant le rendu. Fenêtre, stockage, thème. Lis ces valeurs après le montage, pas pendant le calcul partagé serveur et client.
  3. Fige la locale et le fuseau. Si tu formates des dates ou des nombres, impose la même locale et le même fuseau des deux côtés, ou fais le formatage après l'hydratation.
  4. Ne tolère aucun avertissement d'hydratation. Traite chaque message de la console comme un bug. Un projet propre n'en a aucun. Chaque avertissement résolu est un double rendu supprimé.

Où tu les trouves : ouvre la console du navigateur sur tes pages principales et cherche les avertissements de non correspondance. Ils nomment souvent le composant fautif. C'est gratuit et ça pointe directement la fuite.

Ce qu'il faut retenir

Une fuite de rendu côté serveur ne crashe pas, et c'est ce qui la rend dangereuse. Quand le serveur et le navigateur ne calculent pas le même résultat, le travail du serveur est jeté et refait côté client, à chaque chargement, sur le fil qui devrait répondre au visiteur. Traque les valeurs non déterministes, les API du navigateur lues trop tôt, les différences de locale, et ne tolère plus aucun avertissement d'hydratation. C'est le cousin direct du travail qui consiste à réduire ce qui est hydraté avec les Server Components, et l'un et l'autre servent la vitesse comme premier levier CRO. Ouvre la console sur ta page principale aujourd'hui, et corrige le premier avertissement que tu y trouves. Tu seras surpris du nombre de projets en production qui en accumulent des dizaines, devenus invisibles à force d'être ignorés. Chacun est un peu de vitesse et de stabilité que tu récupères gratuitement. Si tu veux savoir ce que ton site reconstruit en silence à chaque visite, c'est le genre de fuite que je débusque dans un diagnostic de performance.