Back

Server-Side Rendering mit Preact

Server-Side Rendering mit Preact

Wenn Sie bereits Apps mit React und Vite gebaut haben, verstehen Sie das Prinzip des Client-Side Rendering. Der Browser lädt ein JavaScript-Bundle herunter, führt es aus und baut das DOM auf. Das funktioniert, aber Nutzer mit langsamen Verbindungen starren auf einen leeren Bildschirm, während das Bundle lädt. Server-Side Rendering mit Preact löst dieses Problem, indem es bereits darstellungsfertiges HTML vom Server ausliefert. Der geringe Runtime-Footprint von Preact macht diesen Ansatz besonders attraktiv für performance-orientierte Anwendungen.

Dieser Artikel erklärt, wie Preact SSR funktioniert, welches Tooling dabei zum Einsatz kommt und wie Hydration das servergerenderte HTML mit einer interaktiven App verbindet.

Die wichtigsten Erkenntnisse

  • Preact SSR rendert Ihren Komponentenbaum serverseitig zu einem HTML-String und liefert Nutzern damit sichtbare Inhalte, bevor JavaScript ausgeführt wird.
  • Das Paket preact-render-to-string stellt synchrone, asynchrone und Streaming-APIs bereit, um unterschiedliche Anwendungsanforderungen abzudecken.
  • Hydration verknüpft Interaktivität mit dem servergerenderten HTML über hydrate statt render und erhält dabei das bestehende DOM.
  • Ein Vite-basierter Workflow mit @preact/preset-vite ist heute der Standard für neue Preact-Projekte mit SSR-Unterstützung.
  • Vermeiden Sie Hydration-Mismatches, indem Sie Server- und Client-Ausgabe konsistent halten – keine Zeitstempel, Zufalls-IDs oder window-Zugriffe während des Server-Durchlaufs.

Was ist Preact SSR und warum ist es relevant?

Mit SSR wird Ihr Komponentenbaum serverseitig zu einem HTML-String gerendert, bevor der Browser überhaupt etwas empfängt. Der Nutzer sieht den Inhalt sofort. JavaScript lädt im Hintergrund nach und sorgt anschließend für die Interaktivität.

Die praktischen Vorteile sind konkret:

  • Schnellere wahrgenommene Ladezeiten – sichtbare Inhalte werden bereits mit der initialen HTTP-Antwort ausgeliefert.
  • Bessere SEO – Crawler lesen vollständig aufgebautes HTML, ohne JavaScript ausführen zu müssen.
  • Robustheit – Seiten bleiben lesbar, selbst wenn clientseitiges JS fehlschlägt oder langsam ist.

Preact eignet sich besonders gut für SSR, da seine kleine Runtime nur minimalen Overhead verursacht.

Das zentrale Werkzeug: preact-render-to-string

Preact SSR basiert auf preact-render-to-string, einem separaten Paket, das das serverseitige Rendering übernimmt.

npm install preact-render-to-string

Synchrones Rendering

Für Komponenten ohne asynchrone Abhängigkeiten wandelt renderToString Ihren Komponentenbaum in einem Durchgang in HTML um:

import { renderToString } from 'preact-render-to-string';

const App = () => <h1>Hello from the server</h1>;
const html = renderToString(<App />);
// → <h1>Hello from the server</h1>

Asynchrones Rendering

Wenn Komponenten Daten abrufen oder Suspense mit lazy geladenen Chunks verwenden, sollten Sie stattdessen renderToStringAsync einsetzen. Diese Funktion wartet auf Promises und asynchrone Rendering-Arbeiten, bevor der finale HTML-String zurückgegeben wird.

import { renderToStringAsync } from 'preact-render-to-string';

const html = await renderToStringAsync(<App />);

Streaming

Bei größeren Seiten ermöglichen Streaming-APIs, HTML stückweise an den Browser zu senden, sobald die jeweiligen Abschnitte gerendert sind. renderToPipeableStream zielt auf Node.js-Streams ab, während renderToReadableStream für Umgebungen mit der Web Streams API gedacht ist – darunter Plattformen wie Cloudflare Workers, Deno und Bun. Streaming verbessert die Time to First Byte (TTFB), ohne auf den vollständigen Renderprozess warten zu müssen.

Preact Hydration: HTML mit Interaktivität verbinden

Das Ausliefern von statischem HTML ist nur die halbe Miete. Damit die Seite interaktiv wird, muss Preact das bestehende DOM hydratisieren – also Event-Listener und State anhängen, ohne komplett neu zu rendern.

import { hydrate } from 'preact';
import { App } from './app.js';

hydrate(<App />, document.getElementById('root'));

Verwenden Sie hydrate statt render, wenn das DOM bereits vom Server erzeugt wurde. render würde das Server-HTML verwerfen und neu aufbauen – was den Zweck untergräbt.

Hydration-Mismatches treten auf, wenn das servergerenderte HTML nicht mit dem übereinstimmt, was der Client rendern würde. Häufige Ursachen sind das Rendern von Zeitstempeln, Zufalls-IDs oder das Auslesen von window während des Server-Durchlaufs. Halten Sie die Komponentenlogik von Server und Client konsistent, um solche Probleme zu vermeiden.

Preact Vite SSR: Das moderne Setup

Für neue Projekte ist ein Vite-basierter Workflow die praktikable Standardlösung. Der SSR-Guide von Vite dokumentiert das Dual-Build-Pattern: ein Build für den Server-Entry und ein weiterer für das Client-Bundle. Preact integriert sich nahtlos über @preact/preset-vite, das JSX, Aliase und Preact-spezifische Konfigurationen übernimmt.

Für Teams, die einen strukturierteren Ausgangspunkt suchen, bietet preact-iso leichtgewichtige Routing- und Prerendering-Utilities, die speziell für Preact-Vite-Projekte entwickelt wurden.

Worauf Sie achten sollten

Preact SSR teilt konzeptionelle Gemeinsamkeiten mit React SSR, ist aber nicht in jedem Implementierungsdetail identisch. Einige React-spezifische SSR-APIs haben keine direkten Entsprechungen, und das Preact-Ökosystem ist kleiner – ein fairer Kompromiss angesichts der Größen- und Performance-Vorteile.

Das zuverlässig funktionierende Muster: Daten vor dem Rendering abrufen, als Props übergeben, serverseitig zu einem String rendern und clientseitig hydratisieren. Beginnen Sie damit und ergänzen Sie Streaming oder fortgeschrittenere Rendering-Patterns erst, wenn ein konkreter Anlass besteht.

Fazit

Preact SSR bietet einen schlanken, performance-orientierten Weg zu servergerenderten Anwendungen, ohne den Overhead eines umfangreicheren Frameworks. Durch die Kombination von preact-render-to-string für den Server-Durchlauf, hydrate für die clientseitige Aktivierung und Vite für die Build-Pipeline erhalten Sie ein Setup, das schnell auslieferbar und leicht nachvollziehbar ist. Starten Sie mit dem grundlegenden Render-and-Hydrate-Flow, halten Sie Server- und Client-Ausgabe konsistent und greifen Sie erst dann zu Streaming, wenn die Skalierung Ihrer Anwendung dies rechtfertigt.

FAQs

Wählen Sie Preact SSR, wenn Bundle-Größe, Cold-Start-Performance oder Edge-Deployment wichtiger sind als der Zugriff auf das breitere React-Ökosystem. Die kleine Runtime von Preact ist ideal für inhaltsreiche Seiten, Marketing-Pages und Workers-basierte Deployments. Bleiben Sie bei React SSR, wenn Sie auf React-spezifische Bibliotheken angewiesen sind oder APIs wie React Server Components benötigen, die Preact nicht nachbildet.

Stellen Sie sicher, dass Server und Client bei gleichen Props dieselbe Ausgabe rendern. Vermeiden Sie nichtdeterministische Werte beim initialen Rendering, etwa Date.now, Math.random oder Browser-spezifische Globals wie window und localStorage. Wenn Sie ausschließlich clientseitigen Inhalt benötigen, rendern Sie serverseitig einen stabilen Platzhalter und aktualisieren Sie ihn innerhalb eines Effects, nachdem die Hydration abgeschlossen ist.

Viele React-Bibliotheken funktionieren über den preact/compat-Alias, der React-Imports auf Preact-Äquivalente mappt. Bibliotheken, die jedoch von React-spezifischen SSR-Features wie React Server Components oder Rendering-Internals abhängen, verhalten sich möglicherweise nicht korrekt. Testen Sie jede Abhängigkeit in Ihrer SSR-Pipeline, bevor Sie sich darauf festlegen.

Wahrscheinlich nicht. Streaming zahlt sich aus, wenn Seiten groß, datenintensiv sind oder Abschnitte unterschiedlich schnell verfügbar werden. Bei einer typischen kleinen Website liefern renderToString oder renderToStringAsync Ergebnisse schnell genug, sodass Streaming nur zusätzliche Komplexität ohne messbaren Nutzen mit sich bringt. Beginnen Sie mit den einfacheren synchronen oder asynchronen APIs und führen Sie Streaming erst ein, wenn die TTFB tatsächlich zum Engpass wird.

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay