Intelligenteres Caching in Next.js: Partial Rendering und wiederverwendbare Komponenten
Sie haben eine Next.js App Router-Anwendung entwickelt. Datenabrufe funktionieren. Seiten werden gerendert. Aber Sie sind unsicher, ob Ihre Caching-Strategie korrekt ist – oder ob Sie überhaupt eine haben. Sie haben erlebt, dass unerwartet veraltete Daten erscheinen, beobachtet, wie dieselbe Datenbankabfrage mehrmals pro Request ausgeführt wird, und sich gefragt, warum manche Routen sich langsam anfühlen, obwohl sie „statisch” sind.
Dieser Artikel erklärt, wie das Data Caching im Next.js App Router tatsächlich funktioniert, wie die drei Cache-Ebenen zusammenwirken und wie Sie wiederverwendbare Server-Komponenten erstellen, die sowohl Datenabruf als auch Caching-Policy kapseln. Wir behandeln außerdem Next.js Partial Prerendering und wie React 19 Partial Rendering komponentenbasierte Caching-Strategien ermöglicht.
Wichtigste Erkenntnisse
- Next.js verwendet drei Cache-Ebenen (Data Cache, Full Route Cache, Router Cache), die bei Requests kaskadierend zusammenwirken
- Komponenten sollten ihre eigene Caching-Policy besitzen, indem sie React’s
cache()für Deduplizierung und Fetch-Optionen für Lebensdauerkontrolle verwenden - Tag-basierte Revalidierung ermöglicht präzise Cache-Invalidierung über mehrere Routen hinweg
- Partial Prerendering (PPR) erlaubt die Kombination statischer Shells mit dynamisch gestreamten Inhalten durch Suspense-Boundaries
Wie die drei Cache-Ebenen zusammenarbeiten
Das Caching in Next.js arbeitet mit drei unterschiedlichen Mechanismen, die bei jedem Request interagieren.
Data Cache
Der Data Cache persistiert Fetch-Ergebnisse über Requests und Deployments hinweg. Wenn Sie fetch mit aktiviertem Caching aufrufen, speichert Next.js die Response serverseitig. Nachfolgende Requests geben gecachte Daten zurück, bis eine Revalidierung erfolgt.
// Für 1 Stunde über alle Requests hinweg gecacht
const posts = await fetch('https://api.example.com/posts', {
next: { revalidate: 3600 }
})
Full Route Cache
Zur Build-Zeit rendert Next.js statische Routen in HTML und RSC-Payloads. Dieser Full Route Cache liefert vorgerenderte Inhalte sofort aus. Rein dynamische Routen überspringen diesen Cache, aber Routen mit statischen Segmenten oder Revalidierung können dennoch statische Shells generieren.
Client-seitiger Router Cache
Der Browser speichert RSC-Payloads während der Navigation im Arbeitsspeicher. Layouts bleiben über Routenwechsel hinweg bestehen. Besuchte Routen werden für die Session im Speicher gecacht und bei der Navigation wiederverwendet, bis sie invalidiert werden.
Diese Ebenen wirken kaskadierend: Die Invalidierung des Data Cache wirkt sich auf nachfolgende Requests aus, und der Full Route Cache oder Router Cache wird beim nächsten Render aktualisiert, der frische Daten benötigt.
Wiederverwendbare gecachte Server-Komponenten erstellen
Das mentale Modell, das Bugs durch veraltete Daten verhindert: Komponenten sollten ihre eigene Caching-Policy besitzen.
// lib/data.ts
import { cache } from 'react'
export const getProduct = cache(async (id: string) => {
const res = await fetch(`https://api.example.com/products/${id}`, {
next: { revalidate: 300, tags: ['products', `product-${id}`] }
})
return res.json()
})
Diese Funktion kann von jeder Komponente aufgerufen werden – Layout, Page oder verschachteltem Child. React’s cache() dedupliziert Aufrufe innerhalb eines einzelnen Render-Durchlaufs. Die next.revalidate-Option steuert die Lebensdauer des Data Cache. Tags ermöglichen präzise Invalidierung.
Verwenden Sie diese Funktion überall ohne Prop Drilling:
// app/products/[id]/page.tsx
export default async function ProductPage({ params }: { params: { id: string } }) {
const { id } = await params
const product = await getProduct(id)
return <ProductDetails product={product} />
}
Cache-Verhalten mit Route Segment Options steuern
Über Fetch-Optionen hinaus steuern Route Segment Configs das Caching auf Routen-Ebene:
// Dynamisches Rendering erzwingen
export const dynamic = 'force-dynamic'
// Revalidierungsperiode für alle Fetches festlegen
export const revalidate = 3600
Für On-Demand-Invalidierung verwenden Sie revalidatePath oder tag-basierte Revalidierung:
// app/actions.ts
'use server'
import { revalidateTag } from 'next/cache'
export async function updateProduct(id: string) {
// await db.product.update(...)
revalidateTag(`product-${id}`)
}
Discover how at OpenReplay.com.
Next.js Partial Prerendering: Die experimentelle Richtung
Next.js Partial Prerendering stellt einen bedeutenden Wandel dar. Anstatt zwischen vollständig statischen oder vollständig dynamischen Routen zu wählen, rendert PPR eine statische Shell vor, während dynamische Inhalte durch Suspense-Boundaries gestreamt werden.
import { Suspense } from 'react'
export default async function ProductPage({ params }: { params: { id: string } }) {
const { id } = await params
return (
<>
{/* Statische Shell - vorgerendert */}
<Header />
<ProductInfo id={id} />
{/* Dynamische Lücke - wird zur Request-Zeit gestreamt */}
<Suspense fallback={<CartSkeleton />}>
<UserCart />
</Suspense>
</>
)
}
Die statischen Teile werden sofort ausgeliefert. Dynamische Abschnitte werden gestreamt, sobald sie aufgelöst sind. Dieses Feature ist noch experimentell – aktivieren Sie es über ppr: true in den experimentellen Optionen Ihrer next.config.js – aber es weist in die Zukunft des Next.js-Cachings.
React 19 und komponentenbasiertes Caching
Das verbesserte Suspense-Verhalten von React 19 ermöglicht granularere Caching-Strategien. In Suspense eingebettete Komponenten können ihren Daten-Lebenszyklus unabhängig verwalten. Mit den experimentellen use cache- und cacheLife-APIs können Sie Komponenten-Subtrees statt ganzer Seiten cachen:
import { cacheLife } from 'next/cache'
async function BlogPosts() {
'use cache'
cacheLife('hours')
const res = await fetch('https://api.example.com/posts')
const posts = await res.json()
return <PostList posts={posts} />
}
Tag-basierte Revalidierung ermöglicht es Teams, gecachte Daten sicher über Routen hinweg zu teilen. Eine Produkt-Komponente, die sowohl in /products/[id] als auch in /checkout verwendet wird, kann einmal invalidiert werden und aktualisiert sich überall.
Fazit
Erstellen Sie Server-Komponenten, die ihre Caching-Policy kapseln. Verwenden Sie React’s cache() für Request-Deduplizierung, Fetch-Optionen für Data-Cache-Kontrolle und Tags für routenübergreifende Invalidierung. Partial Prerendering ist experimentell, aber es lohnt sich, es zu verstehen – dorthin bewegt sich das Next.js-Caching.
Das Ziel ist nicht maximales Caching. Es ist vorhersagbares Caching, das den tatsächlichen Aktualitätsanforderungen Ihrer Daten entspricht.
FAQs
React's cache() dedupliziert Funktionsaufrufe innerhalb eines einzelnen Render-Durchlaufs und verhindert, dass dieselben Daten während eines Requests mehrfach abgerufen werden. Next.js Fetch-Caching persistiert Ergebnisse über mehrere Requests und Deployments hinweg mithilfe des Data Cache. Verwenden Sie beides zusammen: cache() für Render-Zeit-Deduplizierung und Fetch-Optionen für Request-übergreifende Persistenz.
Verwenden Sie revalidateTag, wenn Sie spezifische Daten über mehrere Routen hinweg invalidieren müssen, z.B. Produktinformationen, die sowohl auf Detail- als auch auf Checkout-Seiten angezeigt werden. Verwenden Sie revalidatePath, wenn Sie alle gecachten Daten für einen bestimmten URL-Pfad invalidieren möchten. Tags bieten präzisere Kontrolle, während Pfade einfacher für Single-Route-Invalidierung sind.
Überprüfen Sie Ihre Build-Ausgabe auf Route-Indikatoren. Statische Routen zeigen ein Kreis-Symbol, während dynamische Routen ein Lambda-Symbol anzeigen. Sie können auch console.log-Statements in Ihren Komponenten hinzufügen – wenn diese bei jedem Request loggen, ist die Route dynamisch. Die Verwendung von cookies(), headers() oder searchParams aktiviert automatisch dynamisches Rendering für Routen.
Partial Prerendering ist ab Next.js 15 noch experimentell. Sie können es zum Testen aktivieren, aber es wird noch nicht für Produktionsanwendungen empfohlen. Die API und das Verhalten können sich in zukünftigen Releases ändern. Beobachten Sie die Next.js-Dokumentation und Release Notes für Stabilitätsupdates, bevor Sie es in der Produktion einsetzen.
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.