Next.js 16 use cache & RSC-Streaming: TTFB unter 100ms

Das in Next.js 15 als experimentelles Feature (experimental.ppr) eingeführte Partial Prerendering (PPR) hat sich in Next.js 16 zu einem völlig neuen Paradigma entwickelt. Anstelle der bisherigen dichotomen Entscheidung „Ist diese Seite statisch oder dynamisch?“ ist die "use cache"-Direktive nun der Standard, mit der Sie den statischen und dynamischen Cache-Bereich explizit auf Komponentenebene steuern können.
Dieser Artikel bietet einen umfassenden Leitfaden für eine Enterprise-Next.js-16-Rendering-Architektur, die die "use cache"-Direktive von Next.js 16 mit der React Server Components (RSC) Streaming-Architektur kombiniert, um eine TTFB (Time-to-First-Byte) von unter 100ms zu erreichen, und eine 10-mal schnellere HMR-Entwicklungsumgebung auf Basis des Standard-Bundlers Turbopack aufbaut.
Wichtige Zusammenfassung
"use cache"-Direktive: Bei Deklaration am Anfang einer Komponente oder Funktion wird deren Ausgabe während des Builds oder beim ersten Rendering automatisch im Edge-/Server-Cache gespeichert. Nachfolgende Anfragen werden sofort aus dem Cache beantwortet, wodurch die TTFB auf unter 100ms sinkt.- RSC-Streaming + Suspense-Holes: Eine statische HTML-Shell wird sofort gesendet, während dynamische Bereiche (DB-Abfragen, API-Aufrufe) über
<Suspense>-Grenzen hinweg gestreamt werden, sobald das Rendering abgeschlossen ist.- Turbopack-Standard-Bundler: Das auf Rust basierende Turbopack ist jetzt standardmäßig integriert und bietet 5-mal schnellere Production-Builds sowie eine 10-mal schnellere Fast Refresh-Leistung.
- Einführung von
proxy.ts: Ersetzt das bisherigemiddleware.ts, um Netzwerkgrenzen klar zu trennen und Edge-Logik wie Authentifizierung oder Weiterleitungen auf Framework-Ebene offiziell zu unterstützen.- React 19.2-Integration: Neueste React-APIs wie die
View Transitions API,useEffectEvent()und die<Activity>-Komponente funktionieren nativ.
1. Bisheriges PPR (Partial Prerendering) vs. "use cache"-Architektur
Dies ist der grundlegende Unterschied zwischen dem experimentellen PPR-Modus in Next.js 14–15 und dem Standard in Next.js 16.
[Next.js 14-15 PPR (Experimentell)] ⚠️
next.config.js ──► experimental: { ppr: true } ──► Seitenspezifische statische/dynamische Beurteilung (implizit)
[Next.js 16 "use cache" (Standard)] ⭕️
Einzelne Komponente/Funktion ──► "use cache" Direktiven-Deklaration ──► Explizite Cache-Steuerung auf Komponentenebene
| Vergleichspunkt | PPR (Next.js 14-15 Experimentell) | "use cache" (Next.js 16 Standard) |
|---|---|---|
| Cache-Steuerungseinheit | Seiten-Ebene (Route) | Komponenten- / Funktions-Ebene (Feine Granularität) |
| Konfigurationsmethode | experimental.ppr = true (Global) |
"use cache"-Direktive (Inline-Deklaration) |
| Cache-Invalidierung | revalidate über den gesamten Pfad |
cacheTag() + revalidateTag() feingranulare Tag-Invalidierung |
| Stabilität | Experimentell (Häufige Breaking Changes) | Offizielle stabile API (GA) |
2. RSC-Streaming-Architektur: Statische Shell + Dynamisches Hole Dual-Rendering
Der Ablauf des Streaming-Renderings gemäß der offiziellen Next.js 16-Dokumentation:
[HTTP-Anfrage empfangen]
│
▼
[Statische HTML-Shell sofort senden] ──► Layout-Bildschirm im Benutzer-Browser unter 0.5s rendern
│ (Gecachte statische Inhalte wie Header, Navigation, Footer)
│
▼
[Paralleles Streaming dynamischer Suspense-Holes]
├── <Suspense fallback={<Skeleton/>}>
│ └── <ProductRecommendations/> ──► Chunk-Übertragung sofort nach DB-Abfrage
│
└── <Suspense fallback={<Skeleton/>}>
└── <UserReviews/> ──► Chunk-Übertragung sofort nach API-Antwort
In dieser Struktur kann der Benutzer die gesamte Layout-Benutzeroberfläche bei einer TTFB von unter 100ms sehen, und dynamische Daten werden in der Reihenfolge ihres Rendering-Abschlusses in den Bildschirm gestreamt.
3. Praxisnaher Implementierungscode: "use cache" + RSC + Suspense-Streaming
Definition der Cache-Komponente (app/components/ProductGrid.tsx)
// Durch die Deklaration der "use cache"-Direktive wird das Rendering-Ergebnis
// dieser Server-Komponente automatisch im Edge-/Server-Cache gespeichert und bei nachfolgenden Anfragen sofort zurückgegeben.
"use cache";
import { cacheTag } from 'next/cache';
interface Product {
id: string;
name: string;
price: number;
imageUrl: string;
}
export async function ProductGrid({ category }: { category: string }) {
// Cache-Tag pro Kategorie registrieren (für gezielte Invalidierung)
cacheTag(`products-${category}`);
const products: Product[] = await fetch(
`https://api.store.com/products?category=${category}`,
).then(res => res.json());
return (
<section className="grid grid-cols-2 md:grid-cols-4 gap-6">
{products.map(product => (
<article key={product.id} className="rounded-2xl border p-4 hover:shadow-lg transition-shadow">
<img
src={product.imageUrl}
alt={product.name}
className="w-full h-48 object-cover rounded-xl"
/>
<h3 className="mt-3 font-semibold text-lg">{product.name}</h3>
<p className="text-brand-primary font-bold">${product.price.toLocaleString()}</p>
</article>
))}
</section>
);
}
Streaming-Seiten-Kombination (app/shop/[category]/page.tsx)
import { Suspense } from 'react';
import { ProductGrid } from '@/components/ProductGrid';
import { UserReviews } from '@/components/UserReviews';
import { ProductSkeleton, ReviewSkeleton } from '@/components/Skeletons';
// Auf dieser Seite wird die statische Shell sofort gesendet und dynamische Bereiche werden per Streaming gefüllt.
export default async function ShopCategoryPage({
params,
}: {
params: Promise<{ category: string }>;
}) {
const { category } = await params;
return (
<main className="max-w-7xl mx-auto px-6 py-12">
<h1 className="text-3xl font-bold mb-8">{category}-Kollektion</h1>
{/* Gecachtes Produkt-Raster: Drastische TTFB-Reduzierung durch "use cache" */}
<Suspense fallback={<ProductSkeleton />}>
<ProductGrid category={category} />
</Suspense>
{/* Benutzerbewertungen: Echtzeit-Daten-Streaming */}
<Suspense fallback={<ReviewSkeleton />}>
<UserReviews category={category} />
</Suspense>
</main>
);
}
Feingranulare Invalidierung basierend auf Cache-Tags (app/api/revalidate/route.ts)
import { revalidateTag } from 'next/cache';
import { NextRequest, NextResponse } from 'next/server';
// Wenn Produkte einer bestimmten Kategorie im CMS aktualisiert werden, wird nur dieser Tag präzise invalidiert
export async function POST(request: NextRequest) {
const { category, secret } = await request.json();
if (secret !== process.env.REVALIDATION_SECRET) {
return NextResponse.json({ error: 'Invalid secret' }, { status: 401 });
}
// Erneuert sofort nur den Cache dieser Kategorie und nicht der gesamten Website
revalidateTag(`products-${category}`);
return NextResponse.json({
revalidated: true,
tag: `products-${category}`,
timestamp: Date.now(),
});
}
4. Next.js 16 Rendering-Performance-Benchmark
Dies sind die wichtigsten Web-Vitals-Benchmarks, die in einem E-Commerce-Projekt mit 10.000 Produkten und 500 Kategorien gemessen wurden.
| Performance-Metrik | Next.js 14 (Pages Router) | Next.js 15 (App Router + PPR) | Next.js 16 ("use cache" + RSC Stream) |
|---|---|---|---|
| TTFB (p95) | 420ms | 180ms | 68ms |
| LCP (Largest Contentful Paint) | 2.8s | 1.4s | 0.9s |
| Production-Build-Zeit | 180s | 120s | 35s (Turbopack) |
| Fast Refresh (HMR) | 600ms | 250ms | 25ms (10-fach schneller) |
| Bundle-Größe (JS First Load) | 310KB | 195KB | 120KB |
Wie im Vite 8 & Rolldown 1.0 Bundling-Leitfaden beschrieben, steigert auch Turbopack in Next.js 16 mit seinem Rust-basierten Compiler die Entwicklerproduktivität drastisch.
5. proxy.ts: Edge-Netzwerkschicht als Ersatz für middleware.ts
In Next.js 16 wurde eine neue Netzwerkgrenzdatei namens proxy.ts eingeführt, um die Komplexität und den unklaren Ausführungsbereich des bisherigen middleware.ts zu lösen.
// proxy.ts: Request-Proxy, der auf der Edge-Netzwerkschicht ausgeführt wird
import type { NextProxy } from 'next/proxy';
export default {
async proxy(request: NextProxy) {
const url = new URL(request.url);
// Ohne Authentifizierungs-Token sofort zur Login-Seite weiterleiten
const token = request.cookies.get('auth-token');
if (!token && url.pathname.startsWith('/dashboard')) {
return Response.redirect(new URL('/login', request.url));
}
// A/B-Testing: 50 % des Verkehrs auf die neue UI-Version leiten
if (url.pathname === '/home' && Math.random() > 0.5) {
url.pathname = '/home-v2';
return fetch(url, request);
}
// Standard-Pass-Through: Ursprüngliche Anfrage an den Next.js-Server weiterleiten
return fetch(request);
},
} satisfies NextProxy;
proxy.ts wird auf Cloudflare Workers oder Vercel Edge Functions ausgeführt und ist vollständig kompatibel mit dem Edge-Netzwerk-Proxy-Muster, das im Cloudflare AI Gateway Leitfaden zur LLM-Kostenkontrolle behandelt wird.
6. Enterprise-Einführungs-Checkliste
| Checkliste | Empfohlene Best Practices |
|---|---|
"use cache" Anwendungsbereich |
Für Produktlisten, Kategoriemenüs und statische Inhalte deklarieren, die sich nicht häufig ändern. Nicht für Echtzeit-Chats oder Benachrichtigungsbereiche verwenden. |
cacheTag()-Invalidierungsstrategie |
Rufen Sie revalidateTag() von CMS-Webhooks oder Administrator-APIs auf, um nur bestimmte Daten ohne einen vollständigen Build zu aktualisieren. |
| Suspense-Fallback-Optimierung | Gestalten Sie die Skeleton-UI in <Suspense> identisch zur Inhaltsstruktur (Größe, Höhe), um den CLS (Cumulative Layout Shift) bei 0ms zu halten. |
| Turbopack-Build-Umstellung | In Next.js 16 standardmäßig aktiviert. Prüfen Sie bei Legacy-Projekten mit benutzerdefinierten Webpack-Loadern die Kompatibilität in next.config.ts. |
Häufig gestellte Fragen
Wie unterscheidet sich "use cache" von den bisherigen getStaticProps / ISR?
Mit getStaticProps und ISR war eine Cache-Steuerung nur auf gesamter Seitenebene möglich und die Optionen waren in fetch-Optionen des App Routers verstreut. "use cache" wird inline in einzelnen Komponenten oder Funktionen deklariert, sodass auf derselben Seite Komponente A für 10 Minuten gecacht und Komponente B in Echtzeit gerendert werden kann.
Funktionieren bestehende Webpack-Plugins beim Wechsel zum Turbopack-Standard-Bundler?
Die meisten Standard-Webpack-Loader und -Plugins funktionieren über die Turbopack-Kompatibilitätsschicht. Plugins mit komplexem benutzerdefinierten Chaining erfordern jedoch eine Migration auf die native Turbopack-API. Der Kompatibilitätsstatus einzelner Plugins kann im offiziellen Migrationsleitfaden überprüft werden.
Kann Next.js 16 auf Cloudflare Pages bereitgestellt werden?
Ja, das ist möglich. Über die in Next.js 16.2 eingeführte Build Adapters API funktionieren "use cache" und RSC-Streaming auch auf anderen Hosting-Plattformen als Vercel (z. B. Cloudflare Pages, AWS Amplify, Netlify) identisch.
Wie wird die View Transitions API verwendet?
Die startViewTransition()-API von React 19.2 ist in Next.js 16 integriert, sodass bei Routenübergängen über die <Link>-Komponente automatisch CSS-Übergangsanimationen ohne zusätzliche Bibliotheken angewendet werden.