Was ist Hydration? Der Schritt, der servergerendertes HTML interaktiv macht

  • vuetelemetry
  • Leitfäden
  • 7 Min. Lesezeit

Servergerendertes HTML bleibt reglos, bis die Hydration Vue daran bindet. Was Hydration tut, warum createSSRApp nötig ist, die drei dokumentierten Ursachen eines Hydration-Mismatch und warum ein Mismatch eher eine stille Performance-Steuer als ein Absturz ist.

Server-side Rendering liefert HTML, das fertig ist, bevor überhaupt JavaScript läuft, und genau deshalb hilft es dem ersten Bildaufbau und den Crawlern. Doch dieses HTML ist reglos. Vues eigene Dokumentation sagt es unverblümt: Wenn Sie auf den Button klicken, ändert sich die Zahl nicht, denn die Seite bleibt statisch, bis das Framework im Browser übernimmt. Hydration ist genau diese Übernahme, also das nachträgliche Beleben des Markups.

Vue beschreibt den Mechanismus präzise. Während der Hydration erzeugt Vue dieselbe Anwendung, die auf dem Server ausgeführt wurde, ordnet jede Komponente den DOM-Knoten zu, die sie steuern soll, und hängt die DOM-Event-Listener an. Wenn es gut läuft, wird nichts von Grund auf neu gebaut: Das Markup ist bereits da, und die Hydration eignet es sich an.

Das Ganze muss man ausdrücklich anfordern, es passiert nicht von selbst. Eine servergerenderte Anwendung im Client zu mounten, verlangt createSSRApp statt createApp, denn damit sagt man Vue, dass das HTML vorgerendert wurde und dass es hydrieren statt neue DOM-Knoten mounten soll. Zur falschen Funktion zu greifen, ist ein verbreiteter Weg, unbemerkt alles zweimal zu rendern.

Wenn die beiden Versionen auseinandergehen

Ein Inspector-Fenster im Browser zeigt einen DOM-Baum aus verschachtelten div- und header-Elementen. Ein Hydration-Mismatch ist eine Abweichung zwischen diesem Baum und dem, was die clientseitige Anwendung erwartet.
Ein Inspector-Fenster im Browser zeigt einen DOM-Baum aus verschachtelten div- und header-Elementen. Ein Hydration-Mismatch ist eine Abweichung zwischen diesem Baum und dem, was die clientseitige Anwendung erwartet.

All das setzt voraus, dass die Server-Ausgabe und die Erwartung des Clients übereinstimmen. Tun sie das nicht, entsteht ein Hydration-Mismatch, den Vue so definiert: Die DOM-Struktur des vorgerenderten HTML entspricht nicht der erwarteten Ausgabe der clientseitigen Anwendung.

Die Dokumentation nennt drei Ursachen, und keine davon ist exotisch.

Die drei dokumentierten Ursachen

Die erste ist ungültige HTML-Verschachtelung. Setzt ein Template ein div in ein p, korrigiert der Parser des Browsers die Struktur schon beim Einlesen des Server-HTML, und das korrigierte DOM passt nicht mehr zu dem, was der Client erwartet. Das Framework hat nichts falsch gemacht: Der Browser hat die Seite umgeschrieben, bevor Vue sie überhaupt zu Gesicht bekam.

  • Hydration erzeugt die auf dem Server ausgeführte Anwendung im Browser neu, ordnet Komponenten den vorhandenen DOM-Knoten zu und hängt Event-Listener an.
  • Sie verlangt createSSRApp statt createApp, was Vue anweist zu hydrieren, statt frische Knoten zu mounten.
  • Ein Hydration-Mismatch liegt vor, wenn das vorgerenderte DOM nicht dem entspricht, was die clientseitige Anwendung erwartet.
  • Vue nennt drei Ursachen: ungültige HTML-Verschachtelung, die der Browser-Parser korrigiert, zufällig erzeugte Werte sowie unterschiedliche Zeitzonen von Server und Client.
  • Vue erholt sich automatisch und die Anwendung läuft weiter, doch verworfene und neu gemountete Knoten kosten Rendering-Performance.

Die zweite sind zufällig erzeugte Werte. Dieselbe Anwendung läuft zweimal, einmal auf dem Server und einmal im Browser, und es ist nicht garantiert, dass ein Zufallswert über beide Durchläufe hinweg identisch ist. Alles, was zur Renderzeit ausgewürfelt wird, läuft auseinander.

Die dritte sind Zeitzonen. Sitzen Server und Client in unterschiedlichen Zonen, stimmen ein während des Serverlaufs formatiertes Datum und dasselbe im Browser formatierte Datum nicht überein. Das ist die Ursache, die in Produktion am längsten überlebt, weil sie nur bei Nutzern am falschen Ort auftritt.

Warum es ein stiller Kostenfaktor ist

Was danach passiert, erklärt, warum sich dieser Fehler so leicht übersehen lässt. Vue versucht, sich automatisch zu erholen, und passt das vorgerenderte DOM an den Client-Zustand an, sodass die Anwendung in der Regel weiterläuft. Der Preis ist ein Verlust an Rendering-Performance, denn falsche Knoten werden verworfen und an ihrer Stelle neue gemountet.

Ein Mismatch ist deshalb selten ein Absturz. Er ist eine stille Steuer: Der Server hat HTML erzeugt, dann wurde ein Teil dieser Arbeit weggeworfen und im Browser erneut erledigt. Sie haben das Server-Rendering zweimal bezahlt und den Nutzen einmal behalten. Genau diese Art von Regression fängt ein funktionaler Test nie ab, weil die Seite weiterhin richtig aussieht.

Ein Mismatch ist deshalb selten ein Absturz. Er ist eine stille Steuer: Der Server hat HTML erzeugt, dann wurde ein Teil dieser Arbeit weggeworfen und im Browser erneut erledigt. Sie haben das Server-Rendering zweimal bezahlt und den Nutzen einmal behalten. Genau diese Art von Regression fängt ein funktionaler Test nie ab, weil die Seite weiterhin richtig aussieht.

- vuetelemetry

Die einfachere Antwort fuer statische Seiten

Sind die Daten, die eine Seite zum Rendern braucht, für alle Nutzer dieselben, verweist Vue auf eine einfachere Antwort als das Rendern pro Anfrage: Static Site Generation, auch Pre-Rendering genannt, bei der die Seite einmal während des Builds gerendert wird. Auf das Ergebnis wird weiterhin hydriert, aber die Serverkosten pro Anfrage entfallen. Bevor man eine SSR-Pipeline optimiert, lohnt die Frage, ob die Seite überhaupt dynamisch sein musste.

Verwandter Stack