Rendering im Web

Veröffentlicht am 6. Februar 2019, zuletzt aktualisiert am 5. Januar 2026

Eine der wichtigsten Entscheidungen, die Webentwickler treffen müssen, ist, wo sie Logik und Rendering in ihrer Anwendung implementieren. Das kann schwierig sein, da es so viele Möglichkeiten gibt, eine Website zu erstellen.

Unser Wissen in diesem Bereich basiert auf unserer Arbeit mit großen Websites in Chrome in den letzten Jahren. Im Allgemeinen empfehlen wir Entwicklern, serverseitiges oder statisches Rendering anstelle einer vollständigen Rehydrierung in Betracht zu ziehen.

Um die Architekturen besser zu verstehen, aus denen wir bei dieser Entscheidung auswählen, benötigen wir eine einheitliche Terminologie und ein gemeinsames Framework für jeden Ansatz. So können Sie die Kompromisse der einzelnen Rendering-Ansätze aus Sicht der Seitenleistung besser bewerten.

Terminologie

Zuerst definieren wir einige Begriffe, die wir verwenden werden.

Rendering

Serverseitiges Rendering (SSR)
Rendern einer App auf dem Server, um HTML anstelle von JavaScript an den Client zu senden.
Clientseitiges Rendering (CSR)
Rendern einer App in einem Browser mithilfe von JavaScript zum Ändern des DOM
Pre-Rendering
Eine clientseitige Anwendung wird zur Build-Zeit ausgeführt, um ihren Ausgangszustand als statischen HTML-Code zu erfassen. Hinweis: „Vorrendern“ in diesem Sinne unterscheidet sich vom Vorrendern zukünftiger Navigationen durch den Browser.
Durstlöscher
Clientseitige Skripts ausführen, um serverseitig gerendertem HTML Anwendungsstatus und Interaktivität hinzuzufügen. Bei der Hydrierung wird davon ausgegangen, dass sich das DOM nicht ändert.
Rehydrierung
Die Begriffe „Hydrierung“ und „Rehydrierung“ werden oft synonym verwendet. „Rehydrierung“ impliziert jedoch, dass das DOM regelmäßig mit dem neuesten Status aktualisiert wird, auch nach der ersten Hydrierung.

Leistung

Time to First Byte (TTFB)
Die Zeit zwischen dem Klicken auf einen Link und dem Laden des ersten Byte des Inhalts auf der neuen Seite.
First Contentful Paint (FCP)
Der Zeitpunkt, zu dem angeforderte Inhalte (Artikeltext usw.) sichtbar werden.
Interaction to Next Paint (INP)
Ein repräsentativer Messwert, der angibt, ob eine Seite durchgehend schnell auf Nutzereingaben reagiert.
Total Blocking Time (TBT)
Ein Proxy-Messwert für INP, der berechnet, wie lange der Haupt-Thread während des Seitenaufbaus blockiert wurde.

Serverseitiges Rendering

Beim serverseitigen Rendering wird das vollständige HTML für eine Seite auf dem Server als Reaktion auf die Navigation generiert. So werden zusätzliche Roundtrips für das Abrufen von Daten und die Vorlagenbearbeitung auf dem Client vermieden, da der Renderer diese Vorgänge ausführt, bevor der Browser eine Antwort erhält.

Serverseitiges Rendering führt in der Regel zu einem schnellen FCP. Wenn Sie die Seitenlogik auf dem Server ausführen und dort rendern, müssen Sie nicht so viel JavaScript an den Client senden. So lässt sich die TBT einer Seite reduzieren, was auch zu einem niedrigeren INP führen kann, da der Hauptthread beim Seitenaufbau nicht so oft blockiert wird. Wenn der Hauptthread seltener blockiert wird, können Nutzerinteraktionen schneller ausgeführt werden.

Das ist sinnvoll, da beim serverseitigen Rendern nur Text und Links an den Browser des Nutzers gesendet werden. Dieser Ansatz kann bei einer Vielzahl von Geräte- und Netzwerkbedingungen gut funktionieren und ermöglicht interessante Browseroptimierungen, z. B. das Streaming von Dokumenten.

Diagramm, das zeigt, wie sich serverseitiges Rendering und die JavaScript-Ausführung auf FCP und TTI auswirken.
FCP und TTI mit serverseitigem Rendering.

Beim serverseitigen Rendern müssen Nutzer seltener warten, bis CPU-intensive JavaScript-Vorgänge ausgeführt werden, bevor sie Ihre Website nutzen können. Auch wenn Sie JavaScript von Drittanbietern nicht vermeiden können, können Sie durch serverseitiges Rendern Ihre eigenen JavaScript-Kosten senken und so mehr Budget für den Rest gewinnen. Dieser Ansatz hat jedoch einen potenziellen Nachteil: Das Generieren von Seiten auf dem Server dauert Zeit, was die TTFB Ihrer Seite erhöhen kann.

Ob serverseitiges Rendering für Ihre Anwendung ausreicht, hängt weitgehend davon ab, welche Art von Anwendung Sie entwickeln. Es gibt eine lange Debatte über die korrekten Anwendungen von serverseitigem und clientseitigem Rendering. Sie können jedoch immer serverseitiges Rendering für einige Seiten und nicht für andere verwenden. Einige Websites haben Hybrid-Rendering-Techniken erfolgreich eingeführt. Netflix rendert beispielsweise seine relativ statischen Landingpages serverseitig, während das JavaScript für interaktionsintensive Seiten prefetching wird. So haben diese clientseitig gerenderten Seiten eine bessere Chance, schnell geladen zu werden.

Mit vielen modernen Frameworks, Bibliotheken und Architekturen können Sie dieselbe Anwendung sowohl auf dem Client als auch auf dem Server rendern. Sie können diese Techniken für das serverseitige Rendern verwenden. Architekturen, bei denen das Rendern sowohl auf dem Server als auch auf dem Client erfolgt, sind jedoch eine eigene Klasse von Lösungen mit sehr unterschiedlichen Leistungsmerkmalen und Kompromissen. React-Nutzer können Server-DOM-APIs oder darauf basierende Lösungen wie Next.js für das serverseitige Rendering verwenden. Vue-Nutzer können die Anleitung zum serverseitigen Rendering von Vue oder Nuxt verwenden. Angular hat Universal.

Die meisten beliebten Lösungen verwenden jedoch eine Form der Hydrierung. Achten Sie daher auf die Ansätze, die Ihr Tool verwendet.

Statisches Rendern

Statisches Rendern erfolgt zur Build-Zeit. Dieser Ansatz bietet einen schnellen FCP sowie einen niedrigeren TBT und INP, sofern Sie die Menge an clientseitigem JavaScript auf Ihren Seiten begrenzen. Im Gegensatz zum serverseitigen Rendering wird auch ein gleichbleibend schneller TTFB erreicht, da das HTML für eine Seite nicht dynamisch auf dem Server generiert werden muss. Beim statischen Rendern wird in der Regel vorab eine separate HTML-Datei für jede URL erstellt. Wenn Sie HTML-Antworten im Voraus generieren, können Sie statische Renderings in mehreren CDNs bereitstellen und so Edge-Caching nutzen.

Diagramm, das zeigt, wie sich statisches Rendering und die optionale JavaScript-Ausführung auf FCP und TTI auswirken.
FCP und TTI mit statischem Rendering.

Es gibt viele verschiedene Lösungen für das statische Rendern. Tools wie Gatsby sind so konzipiert, dass Entwickler den Eindruck haben, ihre Anwendung werde dynamisch gerendert und nicht als Build-Schritt generiert. Tools zur Generierung statischer Websites wie 11ty, Jekyll und Metalsmith nutzen die statische Natur und bieten einen stärker vorlagenbasierten Ansatz.

Einer der Nachteile des statischen Renderings ist, dass für jede mögliche URL individuelle HTML-Dateien generiert werden müssen. Das kann schwierig oder sogar unmöglich sein, wenn Sie diese URLs im Voraus vorhersagen müssen und es sich um Websites mit einer großen Anzahl eindeutiger Seiten handelt.

React-Nutzer kennen vielleicht Gatsby, den statischen Export von Next.js oder Navi. Mit diesen Tools lassen sich Seiten ganz einfach aus Komponenten erstellen. Statisches Rendering und Prerendering verhalten sich jedoch unterschiedlich: Statisch gerenderte Seiten sind interaktiv, ohne dass viel clientseitiges JavaScript ausgeführt werden muss. Prerendering verbessert hingegen den FCP einer Single-Page-Anwendung, die auf dem Client gestartet werden muss, damit Seiten wirklich interaktiv sind.

Wenn Sie sich nicht sicher sind, ob eine bestimmte Lösung statisches Rendern oder Prerendering verwendet, deaktivieren Sie JavaScript und laden Sie die Seite, die Sie testen möchten. Bei statisch gerenderten Seiten sind die meisten interaktiven Funktionen auch ohne JavaScript verfügbar. Vorgerenderte Seiten haben möglicherweise noch einige grundlegende Funktionen wie Links, bei denen JavaScript deaktiviert ist. Der Großteil der Seite ist jedoch inaktiv.

Ein weiterer nützlicher Test ist die Netzwerkdrosselung in den Chrome-Entwicklertools. Damit können Sie sehen, wie viel JavaScript heruntergeladen wird, bevor eine Seite interaktiv wird. Für das Prerendering ist in der Regel mehr JavaScript erforderlich, damit die Seite interaktiv wird. Dieses JavaScript ist in der Regel komplexer als der Ansatz der progressiven Verbesserung, der beim statischen Rendern verwendet wird.

Serverseitiges Rendering im Vergleich zum statischen Rendering

Serverseitiges Rendern ist nicht für alle Anwendungsfälle die beste Lösung, da die dynamische Natur erhebliche Rechenkosten verursachen kann. Viele serverseitige Rendering-Lösungen führen nicht zu einem schnellen Flush, verzögern TTFB oder verdoppeln die gesendeten Daten (z. B. Inline-Status, die von JavaScript auf dem Client verwendet werden). In React kann renderToString() langsam sein, da es synchron und Single-Threaded ist. Neuere React-Server-DOM-APIs unterstützen Streaming. So kann der erste Teil einer HTML-Antwort schneller an den Browser gesendet werden, während der Rest noch auf dem Server generiert wird.

Für ein „korrektes“ serverseitiges Rendern ist es unter Umständen erforderlich, eine Lösung für Komponentencaching zu finden oder zu entwickeln, den Arbeitsspeicherverbrauch zu verwalten, Memoization-Techniken zu verwenden und andere Aspekte zu berücksichtigen. Sie verarbeiten oder erstellen dieselbe App häufig zweimal, einmal auf dem Client und einmal auf dem Server. Serverseitiges Rendern, bei dem Inhalte früher angezeigt werden, bedeutet nicht unbedingt weniger Arbeit für Sie. Wenn Sie viel Arbeit auf dem Client haben, nachdem eine vom Server generierte HTML-Antwort auf dem Client eingegangen ist, kann dies immer noch zu höheren TBT- und INP-Werten für Ihre Website führen.

Beim serverseitigen Rendering wird HTML für jede URL bei Bedarf generiert. Das kann jedoch langsamer sein als das Bereitstellen statisch gerenderter Inhalte. Wenn Sie den zusätzlichen Aufwand nicht scheuen, können Sie die serverseitige Renderingzeit durch serverseitiges Rendering in Kombination mit HTML-Caching erheblich verkürzen. Der Vorteil des serverseitigen Renderings besteht darin, dass mehr „Live“-Daten abgerufen und auf eine größere Anzahl von Anfragen reagiert werden kann als beim statischen Rendering. Seiten, die personalisiert werden müssen, sind ein konkretes Beispiel für Anfragetypen, die sich nicht gut für das statische Rendern eignen.

Beim Erstellen einer PWA kann serverseitiges Rendering auch interessante Entscheidungen mit sich bringen. Ist es besser, das Caching von Service Workern für die gesamte Seite zu verwenden oder einzelne Inhalte serverseitig zu rendern?

Clientseitiges Rendering

Beim clientseitigen Rendering werden Seiten direkt im Browser mit JavaScript gerendert. Alle Logik, Datenabrufe, Vorlagen und das Routing werden auf dem Client statt auf dem Server verarbeitet. Das Ergebnis ist, dass mehr Daten vom Server an das Gerät des Nutzers übertragen werden, was mit eigenen Nachteilen verbunden ist.

Die clientseitige Darstellung kann schwierig zu implementieren und für Mobilgeräte schnell zu halten sein. Mit etwas Aufwand, um ein knappes JavaScript-Budget einzuhalten und den Wert in so wenigen Roundtrips wie möglich zu liefern, können Sie das clientseitige Rendering fast so leistungsstark wie das reine serverseitige Rendering machen. Sie können den Parser schneller zum Laufen bringen, indem Sie kritische Skripts und Daten über <link rel=preload> bereitstellen. Wir empfehlen außerdem, Muster wie PRPL zu verwenden, damit sich erste und nachfolgende Navigationsvorgänge sofort anfühlen.

Diagramm
    zum clientseitigen Rendering, das sich auf FCP und TTI auswirkt.
FCP und TTI mit clientseitigem Rendering.

Der Hauptnachteil des clientseitigen Renderings besteht darin, dass die Menge an JavaScript, die erforderlich ist, mit dem Wachstum einer Anwendung zunimmt, was sich auf den INP einer Seite auswirken kann. Das wird besonders schwierig, wenn neue JavaScript-Bibliotheken, Polyfills und Drittanbietercode hinzukommen, die um Rechenleistung konkurrieren und oft verarbeitet werden müssen, bevor der Inhalt einer Seite gerendert werden kann.

Bei Anwendungen, die clientseitiges Rendering verwenden und auf große JavaScript-Bundles angewiesen sind, sollte aggressives Code-Splitting in Betracht gezogen werden, um TBT und INP beim Seitenaufbau zu senken. Außerdem sollte JavaScript per Lazy Loading geladen werden, damit nur das bereitgestellt wird, was der Nutzer benötigt und wenn es benötigt wird. Bei Anwendungen mit wenig oder keiner Interaktivität kann serverseitiges Rendering eine skalierbarere Lösung für diese Probleme darstellen.

Wenn Sie Single-Page-Anwendungen entwickeln, können Sie die Caching-Technik für die Anwendungsshell anwenden, indem Sie die wichtigsten Teile der Benutzeroberfläche identifizieren, die von den meisten Seiten gemeinsam genutzt werden. In Kombination mit Service Workern kann dies die wahrgenommene Leistung bei wiederholten Besuchen erheblich verbessern, da die Seite das HTML und die Abhängigkeiten der Anwendungsshell sehr schnell aus CacheStorage laden kann.

Bei der Rehydrierung werden serverseitiges und clientseitiges Rendering kombiniert.

Hydration ist ein Ansatz, mit dem die Nachteile zwischen clientseitigem und serverseitigem Rendering durch beide Ansätze gemindert werden. Navigationsanfragen wie das Laden oder Neuladen einer vollständigen Seite werden von einem Server verarbeitet, der die Anwendung in HTML rendert. Das für das Rendern verwendete JavaScript und die Daten werden dann in das resultierende Dokument eingebettet. Bei sorgfältiger Ausführung wird so ein schneller FCP wie beim serverseitigen Rendern erreicht. Anschließend wird das Rendern auf dem Client fortgesetzt.

Das ist eine effektive Lösung, kann aber erhebliche Leistungseinbußen mit sich bringen.

Der größte Nachteil des serverseitigen Renderings mit Rehydrierung besteht darin, dass es sich negativ auf TBT und INP auswirken kann, auch wenn es FCP verbessert. Serverseitig gerenderte Seiten können geladen und interaktiv erscheinen, reagieren aber erst auf Eingaben, wenn die clientseitigen Skripts für Komponenten ausgeführt und Event-Handler angehängt wurden. Auf Mobilgeräten kann das mehrere Minuten dauern, was für den Nutzer verwirrend und frustrierend sein kann.

Ein Rehydrierungsproblem: Eine App zum Preis von zwei

Damit das clientseitige JavaScript genau dort weitermachen kann, wo der Server aufgehört hat, ohne alle Daten noch einmal anzufordern, mit denen der Server sein HTML gerendert hat, serialisieren die meisten serverseitigen Renderinglösungen die Antwort aus den Datenabhängigkeiten einer Benutzeroberfläche als Script-Tags im Dokument. Da dadurch viel HTML dupliziert wird, kann die Rehydrierung mehr Probleme als nur eine verzögerte Interaktivität verursachen.

HTML-Dokument mit serialisierter Benutzeroberfläche, Inline-Daten und einem bundle.js-Script.

Der Server gibt als Reaktion auf eine Navigationsanfrage eine Beschreibung der Benutzeroberfläche der Anwendung zurück. Er gibt aber auch die Quelldaten zurück, die zum Erstellen dieser Benutzeroberfläche verwendet werden, sowie eine vollständige Kopie der Implementierung der Benutzeroberfläche, die dann auf dem Client gestartet wird. Die Benutzeroberfläche wird erst interaktiv, nachdem bundle.js geladen und ausgeführt wurde.

Leistungsmesswerte, die von echten Websites mit serverseitigem Rendering und Rehydrierung erfasst wurden, deuten darauf hin, dass dies selten die beste Option ist. Der wichtigste Grund ist die Auswirkung auf die Nutzerfreundlichkeit, wenn eine Seite zwar fertig aussieht, aber keine der interaktiven Funktionen funktioniert.

Die negativen Auswirkungen des clientseitigen Renderings auf die TTI.

Es gibt Hoffnung für serverseitiges Rendering mit Rehydration. Kurzfristig kann die TTFB reduziert werden, wenn nur serverseitiges Rendering für Inhalte verwendet wird, die sich gut im Cache speichern lassen. Das Ergebnis ist dann ähnlich wie beim Prerendering. Die inkrementelle, progressive oder teilweise Rehydrierung könnte der Schlüssel sein, um diese Technik in Zukunft praktikabler zu machen.

Serverseitiges Rendering streamen und progressiv rehydrieren

Das serverseitige Rendering hat sich in den letzten Jahren weiterentwickelt.

Mit Streaming-serverseitigem Rendering können Sie HTML in Chunks senden, die der Browser nach und nach rendern kann, sobald sie empfangen werden. So können Sie Markup schneller an Ihre Nutzer senden und den FCP beschleunigen. In React sind Streams in renderToPipeableStream() asynchron, im Vergleich zu synchronen renderToString(). Das bedeutet, dass der Rückstau gut gehandhabt wird.

Progressive Rehydration ist ebenfalls eine Überlegung wert (React hat sie implementiert). Bei diesem Ansatz werden einzelne Teile einer serverseitig gerenderten Anwendung nach und nach „hochgefahren“, anstatt die gesamte Anwendung auf einmal zu initialisieren, wie es derzeit üblich ist. So kann die Menge an JavaScript reduziert werden, die erforderlich ist, um Seiten interaktiv zu machen. Sie können das clientseitige Upgrade von Teilen der Seite mit niedriger Priorität aufschieben, um zu verhindern, dass der Hauptthread blockiert wird. Dadurch können Nutzerinteraktionen schneller erfolgen, nachdem der Nutzer sie initiiert hat.

Die progressive Rehydrierung kann Ihnen auch helfen, eine der häufigsten Fallstricke bei der serverseitigen Rendering-Rehydrierung zu vermeiden: Ein serverseitig gerenderter DOM-Baum wird zerstört und dann sofort neu aufgebaut, meistens, weil für das anfängliche synchrone clientseitige Rendering Daten erforderlich waren, die noch nicht ganz bereit waren, oft ein Promise, das noch nicht aufgelöst wurde.

Teilweise Rehydrierung

Die teilweise Rehydrierung hat sich als schwierig zu implementieren erwiesen. Dieser Ansatz ist eine Erweiterung der progressiven Rehydrierung, bei der einzelne Teile der Seite (Komponenten, Ansichten oder Bäume) analysiert und die Teile mit geringer oder keiner Interaktivität identifiziert werden. Für jeden dieser meist statischen Teile wird der entsprechende JavaScript-Code in inerte Referenzen und dekorative Elemente umgewandelt, wodurch der clientseitige Speicherbedarf auf nahezu null reduziert wird.

Die teilweise Rehydrierung birgt eigene Probleme und Kompromisse. Das stellt einige interessante Herausforderungen für das Caching dar. Außerdem können wir bei der clientseitigen Navigation nicht davon ausgehen, dass serverseitig gerendertes HTML für inerte Teile der Anwendung ohne vollständigen Seitenaufbau verfügbar ist.

Trisomorphes Rendering

Wenn Service Worker für Sie infrage kommen, sollten Sie trisomorphes Rendern in Betracht ziehen. Mit dieser Technik können Sie das serverseitige Streaming-Rendering für anfängliche oder nicht JavaScript-basierte Navigationen verwenden. Anschließend kann Ihr Service Worker das Rendern von HTML für Navigationen übernehmen, nachdem er installiert wurde. So können zwischengespeicherte Komponenten und Vorlagen auf dem neuesten Stand gehalten und SPA-ähnliche Navigationsvorgänge zum Rendern neuer Ansichten in derselben Sitzung ermöglicht werden. Dieser Ansatz funktioniert am besten, wenn Sie denselben Vorlagen- und Routingcode für Server, Clientseite und Service Worker verwenden können.

Trisomorphes Rendering, bei dem ein Browser und ein Service Worker mit dem Server kommunizieren.

SEO-Überlegungen

Bei der Auswahl einer Web-Rendering-Strategie berücksichtigen Teams häufig die Auswirkungen auf die SEO. Serverseitiges Rendern ist eine beliebte Methode, um eine „vollständig aussehende“ Darstellung zu liefern, die Crawler interpretieren können. Crawler können JavaScript verstehen, aber es gibt oft Einschränkungen bei der Darstellung. Clientseitiges Rendern kann funktionieren, erfordert aber oft zusätzliche Tests und Aufwand. In letzter Zeit ist auch dynamisches Rendering eine Option, die in Betracht gezogen werden sollte, wenn Ihre Architektur stark von clientseitigem JavaScript abhängt.

Fazit

Wenn Sie sich für einen Rendering-Ansatz entscheiden, sollten Sie messen und verstehen, wo Ihre Engpässe liegen. Überlegen Sie, ob statisches oder serverseitiges Rendering die meisten Anforderungen erfüllen kann. Es ist in Ordnung, hauptsächlich HTML mit minimalem JavaScript zu verwenden, um eine interaktive Benutzeroberfläche zu erstellen. Hier ist eine praktische Infografik, die das Server-Client-Spektrum zeigt:

Rendering-Optionen und ihre Vor- und Nachteile.

Gutschriften

Vielen Dank an alle für ihre Rezensionen und Inspirationen:

Jeffrey Posnick, Houssein Djirdeh, Shubhie Panicker, Chris Harrelson und Sebastian Markbåge.