Erklärung zur teilweisen Vorkonvertierung und zur gleichzeitigen Konvertierung
Erfahren Sie, wie sowohl das partielle Vorkompilieren von Next.js als auch das parallele Rendering von React langsame Anwendungen beheben, indem sie den Frameworks ermöglichen, Aufgaben zu planen und schrittweise auszuführen, anstatt die Renderungen als eine blockierende Einheit zu betrachten.
Die modernen Leistungsoptimierungen für React und Next.js kehren immer wieder zu derselben Erkenntnis zurück: Wenn eine ganze Seite oder ein gesamter Renderprozess wie eine einzige, ununterbrochene Einheit funktionieren muss, wirken Anwendungen langsam. Zwei Techniken adressieren dieses Problem aus unterschiedlichen Perspektiven – das partielle Vorendern, das es einer einzelnen Next.js-Route ermöglicht, statische und dynamische Inhalte zu kombinieren, sowie das parallele Rendern, das es React erlaubt, Arbeiten im Browser zu unterbrechen und neu anzuordnen. Gemeinsam zeigen sie ein Muster, das es zu verstehen lohnt: Leistungsverbesserungen ergeben sich zunehmend nicht daraus, „schnellere“ Code zu schreiben, sondern dadurch, dass das Framework die Aufgaben intelligenter planen und ausführen kann.
Die alte Wahl zwischen vollständigem oder gar keinem Rendern
Über einen langen Zeitraum hatte eine Next.js-Seite genau zwei Rendermodi zur Auswahl:
- Statische Generierung (SSG) – Seiten werden schnell bereitgestellt, da sie im Voraus erstellt werden, doch der Inhalt wird veraltet, bis er neu generiert wird.
- Serverseitige Renderung (SSR) – der Inhalt ist stets aktuell, doch jeder Anfrage muss auf den langsamsten Datenpunkt gewartet werden, bevor etwas zurückgesendet wird.
Das Problem ist, dass die meisten echten Seiten nicht eindeutig in eine dieser Kategorien passen. Eine Produktseite ist beispielsweise größtenteils statisch – Layout, Navigation und Werbetexte ändern sich nicht mit jeder Anfrage – enthält aber auch einige wirklich dynamische Elemente wie ein Warenkorb-Icon oder eine Echtzeit-Auftragsanzeige. Die gesamte Seite über SSR zu rendern, nur um ein kleines Widget aktuell zu halten, bedeutet, die vollen Kosten der Serverrenderung für Inhalt aufzubringen, der das nicht benötigt.
Eine Route sowohl statisch als auch dynamisch gestalten
Partial Pre-rendering (PPR) existiert, um diese Lücke zu schließen. Es ermöglicht es einer einzigen Route, sofort eine statische Struktur bereitzustellen, während die darin enthaltenen dynamischen Teile so schnell wie möglich gestreamt werden, sobald ihre Daten verfügbar sind – ohne separate Seiten und ohne Wechsel zwischen getStaticProps und getServerSideProps.
// app/product/[id]/page.tsx
import { Suspense } from 'react';
import ProductShell from '@/components/ProductShell';
import LiveInventory from '@/components/LiveInventory';
export default function ProductPage({ params }: { params: { id: string } }) {
return (
<ProductShell productId={params.id}>
{/* static instantly, no waiting on the network */}
<Suspense fallback={<InventorySkeleton />}>
{/* streamed in once the dynamic data resolves */}
<LiveInventory productId={params.id} />
</Suspense>
</ProductShell>
);
}
Das Mechanismus ist eine Suspense-Grenze. Alles, was außerhalb davon platziert wird, wird zur Zeit der Kompilierung vorgerendert und sofort bereitgestellt; alles, was darin eingebettet ist, wird zur Zeit der Anfrage berechnet und gestreamt. Das ist das gesamte Konzept: ein Datei, eine Route, zwei koexistierende Renderungsstrategien.
Diese Aufteilung bringt mehrere konkrete Vorteile mit sich. Die Zeit bis zum ersten Byte verringert sich, da die statische Seite direkt vom Server bereitgestellt wird, anstatt für jeden Anfragevorgang neu berechnet zu werden. Ebenso entfällt ein vollständiger Ladezustand der Seite – Besucher sehen sofort die sinnvollen, statischen Teile der Seite, während die kleineren dynamischen Elemente nach und nach hinzugefügt werden. Zudem ist die mentale Belastung geringer als bei der Verwaltung separater statischer und serverseitig generierter Seiten, da man mit nur einer Route und einem einzigen Datei arbeitet, das einfach verschiedene Strategien kombiniert. Das Next.js-Team beschreibt das Ziel damit, die Vorteile sowohl der statischen als auch der dynamischen Darstellung ohne die üblichen architektonischen Kompromisse zu bieten.
Eine Handvoll praktischer Richtlinien sorgen dafür, dass PPR in der Produktion effektiv ist. Halten Sie die Suspense-Grenzen eng um nur die wirklich dynamischen Teile – zu viel Inhalt einzuschließen vereitelt den Sinn des Vorkompilierens ganz. Halten Sie die Ersatzskelette leicht, da diese Ersatzversionen selbst Teil der statisch gerenderten Struktur sind. Wenn Sie TypeScript verwenden, definieren Sie klare Eigenschaftsverträge zwischen der statischen Struktur und den eingestreamten Komponenten, damit beide Teile im Laufe der Entwicklung synchron bleiben. Und beim Testen begrenzen Sie die Verbindung in den Entwicklertools Ihres Browsers auf etwas wie langsames 3G – die Vorteile von PPR werden unter realistischen Netzwerkbedingungen viel deutlicher als über eine schnelle lokale Verbindung.
Falls Ihr Team Next.js 14 oder neuer verwendet, lohnt es sich, PPR zunächst auf einer einzigen Route auszuprobieren, bevor man es in der gesamten Anwendung einsetzt. Es handelt sich dabei nicht um einen Marketingbegriff, sondern um eine Render-Strategie, die endlich dem tatsächlichen Verhalten echter Seiten entspricht – teilweise statisch, teilweise dynamisch, gleichzeitig.
Erweiterung dieser Idee auf Client-Side Rendering
Partial Pre-rendering löst die Trennung zwischen statischen und dynamischen Inhalten auf Server- und Netzwerkebene. Concurrent Rendering, das mit React 18 eingeführt und in React 19 weiter verbessert wurde, löst ein ähnliches Problem im Browser: Anstatt zwischen „Alles sofort rendern“ und „Noch nichts rendern“ zu wählen, kann React nun einige Elemente sofort rendern und andere warten lassen.
Vor React 18 war das Rendering synchron und blockierend. Ein einziger Zustandsupdate löste ein Neurendern aus, das unabhängig von allen Umständen zu Ende geführt wurde – selbst wenn dadurch das Scrollen oder Eingeben eingefroren werden musste, während React den gesamten Zustandsbaum verarbeitete.
Durch das konkurrierende Rendering ändert sich dieses Verhalten. React kann nun ein Renderen mitten im Lauf pausieren, dringende Updates wie Tippen oder Klicken gegenüber weniger dringenden Updates wie dem Filtern einer langen Liste priorisieren und laufende Arbeiten ignorieren, wenn ein neueres Update sie überflüssig macht. Wichtig ist, dass es sich dabei nicht um eine neue API handelt, die man von Grund auf lernen muss – es ist vielmehr ein anderes Scheduling-Modell, das hinter den bereits verwendeten Hooks aktiv ist.
Die Hooks, die das konkurrierende Scheduling ermöglichen
useTransition erlaubt es, einen Zustandsupdate als weniger dringend zu markieren, sodass React die Benutzeroberfläche weiterhin responsiv halten kann, während der Update im Hintergrund verarbeitet wird.
function ProductSearch() {
const [query, setQuery] = useState("");
const [results, setResults] = useState([]);
const [isPending, startTransition] = useTransition();
function handleChange(e) {
const value = e.target.value;
setQuery(value); // urgent — keep input snappy
startTransition(() => {
// non-urgent — can be interrupted
setResults(filterProducts(value));
});
}
return (
<>
<input value={query} onChange={handleChange} />
{isPending && <span className="text-gray-400">Updating…</span>}
<ResultsList items={results} />
</>
);
}
Mit diesem Muster bleibt das Eingeben in ein Suchfeld reibungslos, selbst während im Hintergrund Tausende von Elementen gefiltert werden.
Suspense übernimmt auf der Client-Seite eine ähnliche Streaming-Funktion wie in PPR auf der Server-Seite: Anstatt die gesamte Seite beim Laden von Daten zu blockieren, ermöglicht es es den einzelnen UI-Elementen, unabhängig voneinander geladen zu werden. In Kombination mit dem Next.js App Router führt dies außerdem dazu, dass Server-Komponenten schrittweise in die Seite eingestreamt werden, anstatt den gesamten Ladevorgang zu verzögern.
useDeferredValue befasst sich mit einem verwandten, aber unterschiedlichen Fall: teure Neuzeichnungen, die durch Werte aus Props oder Context verursacht werden und nicht durch den lokalen Zustand der Komponente. Es ermöglicht es React, die Berechnung dieser aufwändigen Teile hinauszuzögern, bis wieder Zeit dafür vorhanden ist.
Für Teams, die mit React, Next.js, TypeScript, Redux und Tailwind CSS arbeiten, ist dieses Scheduling-Modell wichtiger als nur die einzelnen Hooks – neuere asynchrone Muster in Redux Toolkit sowie das Verhalten von Next.js Server Actions im Hintergrund stützen sich beide auf dasselbe zugrunde liegende konkurrente Scheduling, das React nun bereitstellt. Konkurrenzfähigkeit ist nichts, was man direkt einschaltet; es handelt sich um eine Funktion, die React automatisch anwendet, sobald Ihre Komponenten so strukturiert sind, dass ihre Darstellung unterbrochen und wieder aufgenommen werden kann.
Was man sich merken sollte
In beiden Techniken bleibt die grundlegende Botschaft dieselbe: Die Verarbeitung einer ganzen Seite oder eines gesamten Renderings als eine untrennbare Einheit verursacht Langsamkeit – nicht unbedingt ineffizienter Code. Konkurrenzloses Rendering geht nicht darum, schnellere Code zu schreiben, sondern um eine intelligente Planung des bereits vorhandenen Codes. In der Praxis bedeutet das, nicht dringende Zustandsaktualisierungen mithilfe von useTransition zu verschieben, Daten mit Suspense zu streamen und auf Geräten mit geringerer Leistung zu testen, da dort die Vorteile der Konkurrenz am deutlichsten sichtbar sind. In Kombination mit dem teilweisen Vorendern auf der Serverseite ermöglichen diese Werkzeuge es einer einzigen Route oder einem einzelnen Komponentenbaum, statische Inhalte sofort bereitzustellen, während dynamische Inhalte erst dann eingestreamt werden, wenn sie fertig sind – das Beste aus beiden Renderingszenarien, ohne die Architektur um eines der Extremen herum neu aufbauen zu müssen.
Verwandte Literatur
- Inside TypeScript 7's Go Rewrite: Speed Gains Without Code Changes — Erfahren Sie, wie der auf Go basierende Compiler von TypeScript 7 bis zu 8-12-mal schnellere Kompiliervorgänge ermöglicht, warum der Architekturwechsel funktioniert und wie bestehende Projekte sicher aktualisiert werden können.
- React 19.2 SSR Primitives: Activity, cacheSignal, and PPR Explained — Erfahren Sie, wie die neuen Komponenten Activity, cacheSignal sowie das Partial Pre-rendering in React 19.2 Entwicklern direkten Einfluss auf die Leistung des Server-Renderings geben.