Qu'est-ce que l'hydration ? L'étape qui rend interactif le HTML rendu côté serveur

  • vuetelemetry
  • Guides
  • 7 min de lecture

Le HTML rendu côté serveur reste inerte tant que l'hydration n'y attache pas Vue. Ce que fait l'hydration, pourquoi createSSRApp est nécessaire, les trois causes documentées d'un mismatch d'hydration, et pourquoi un mismatch est une taxe silencieuse sur les performances plutôt qu'un plantage.

Le rendu côté serveur produit un HTML déjà complet avant l'exécution du moindre JavaScript, ce qui explique qu'il aide le premier affichage et les robots d'indexation. Mais ce HTML est inerte. La documentation de Vue le dit sans détour : si vous cliquez sur le bouton, le nombre ne change pas, parce que la page reste statique tant que le framework n'a pas pris le relais dans le navigateur. L'hydration, c'est cette prise de relais.

Vue décrit le mécanisme avec précision. Pendant l'hydration, il crée la même application Vue que celle exécutée sur le serveur, associe chaque composant aux nœuds DOM qu'il doit contrôler, et attache les écouteurs d'événements du DOM. Quand tout se passe bien, rien n'est reconstruit de zéro : le balisage est déjà là, et l'hydration s'en empare.

Le mécanisme se demande explicitement, il ne se déclenche pas tout seul. Monter dans le navigateur une application rendue par le serveur exige createSSRApp et non createApp, car c'est ce qui indique à Vue que le HTML a été pré-rendu et qu'il doit hydrater plutôt que monter de nouveaux nœuds DOM. Se tromper de fonction est un moyen courant de tout rendre deux fois sans s'en apercevoir.

Quand les deux versions divergent

Panneau d'inspection d'un navigateur affichant un arbre DOM composé d'éléments div et header imbriqués. Un mismatch d'hydration est un désaccord entre cet arbre et ce qu'attend l'application côté client.
Panneau d'inspection d'un navigateur affichant un arbre DOM composé d'éléments div et header imbriqués. Un mismatch d'hydration est un désaccord entre cet arbre et ce qu'attend l'application côté client.

Tout cela suppose que la sortie du serveur et l'attente du client concordent. Quand ce n'est pas le cas, vous obtenez un mismatch d'hydration, que Vue définit comme le fait que la structure DOM du HTML pré-rendu ne correspond pas à la sortie attendue par l'application côté client.

La documentation nomme trois causes, et aucune n'a rien d'exotique.

Les trois causes documentees

La première est une imbrication HTML invalide. Si un template place un div à l'intérieur d'un p, le parseur du navigateur corrige lui-même la structure pendant la lecture du HTML serveur, et le DOM ainsi corrigé ne correspond plus à ce qu'attend le client. Le framework n'a rien fait de mal : le navigateur a réécrit la page avant même que Vue ne la voie.

  • L'hydration recrée dans le navigateur l'application exécutée sur le serveur, associe les composants aux nœuds DOM existants et attache les écouteurs d'événements.
  • Elle exige createSSRApp plutôt que createApp, ce qui indique à Vue d'hydrater au lieu de monter de nouveaux nœuds.
  • Un mismatch d'hydration, c'est quand le DOM pré-rendu ne correspond pas à ce qu'attend l'application côté client.
  • Vue nomme trois causes : une imbrication HTML invalide corrigée par le parseur du navigateur, des valeurs générées aléatoirement, et des fuseaux horaires différents entre serveur et client.
  • Vue récupère automatiquement et l'application continue de fonctionner, mais les nœuds jetés puis remontés coûtent en performance de rendu.

La deuxième concerne les valeurs générées aléatoirement. La même application tourne deux fois, une fois sur le serveur et une fois dans le navigateur, et rien ne garantit qu'une valeur aléatoire soit identique entre ces deux exécutions. Tout ce qui est tiré au moment du rendu finira par diverger.

La troisième tient aux fuseaux horaires. Quand le serveur et le client se trouvent dans des fuseaux différents, une date formatée pendant l'exécution serveur et la même date formatée dans le navigateur ne concorderont pas. C'est la cause qui survit le plus longtemps en production, parce qu'elle n'apparaît que pour les utilisateurs situés au mauvais endroit.

Pourquoi c est un cout silencieux

Ce qui se passe ensuite explique pourquoi ce bug est si facile à ignorer. Vue tente de récupérer automatiquement et ajuste le DOM pré-rendu pour le faire correspondre à l'état du client, si bien que l'application continue généralement de fonctionner. Le prix à payer est une perte de performance de rendu, car les nœuds incorrects sont jetés et de nouveaux sont montés à leur place.

Un mismatch est donc rarement un plantage. C'est une taxe silencieuse : le serveur a produit du HTML, puis une partie de ce travail a été jetée et refaite dans le navigateur. Vous avez payé le rendu côté serveur deux fois et vous n'en gardez le bénéfice qu'une seule. C'est exactement le genre de régression qu'un test fonctionnel n'attrape jamais, puisque la page reste correcte.

Un mismatch est donc rarement un plantage. C'est une taxe silencieuse : le serveur a produit du HTML, puis une partie de ce travail a été jetée et refaite dans le navigateur. Vous avez payé le rendu côté serveur deux fois et vous n'en gardez le bénéfice qu'une seule. C'est exactement le genre de régression qu'un test fonctionnel n'attrape jamais, puisque la page reste correcte.

- vuetelemetry

La reponse plus simple pour les pages statiques

Si les données nécessaires au rendu d'une page sont les mêmes pour tous les utilisateurs, Vue indique une réponse plus simple que le rendu à chaque requête : la génération de site statique, aussi appelée pré-rendu, où la page est rendue une seule fois pendant le build. L'hydration s'applique toujours au résultat, mais le coût serveur par requête disparaît. Avant d'optimiser une chaîne SSR, il vaut la peine de se demander si la page avait vraiment besoin d'être dynamique.

Stack liée