Data-Caching und Revalidierung im Next.js App Router verstehen
Grace Collins
Solutions Engineer · Leapcell

Einleitung
In der schnelllebigen Welt der Webentwicklung ist die Bereitstellung einer schnellen und reaktionsfähigen Benutzererfahrung von größter Bedeutung. Eine der effektivsten Methoden, dies zu erreichen, ist intelligentes Data-Caching. Diese leistungsstarke Optimierung kann jedoch auch unerwartete Verhaltensweisen hervorrufen, die Entwickler zu dem Ausruf veranlassen: „Warum wird meine Fetch-Anfrage zwischengespeichert?“ Dies ist ein besonders häufiger Diskussionspunkt bei der Arbeit mit modernen Frameworks wie Next.js, insbesondere mit der Einführung seines App Routers. Das Verständnis, wie Next.js Data-Caching und Revalidierung handhabt, ist entscheidend für die Erstellung performanter und vorhersehbarer Anwendungen, und genau das werden wir in diesem Artikel untersuchen. Wir werden die Schichten abbauen, um die ausgeklügelten Strategien aufzudecken, die Next.js zur Verwaltung Ihrer Daten einsetzt, und sicherzustellen, dass Sie stets die Kontrolle darüber haben, was Ihre Benutzer sehen.
Kernkonzepte
Bevor wir uns mit den Feinheiten der Caching-Mechanismen von Next.js befassen, lassen Sie uns einige grundlegende Begriffe definieren, die für unsere Diskussion zentral sein werden:
- Caching: Der Prozess der Speicherung von Kopien von Daten oder Dateien an einem temporären Speicherort, sodass zukünftige Anfragen für diese Daten schneller bedient werden können.
 - Revalidierung: Der Prozess der Überprüfung der Cache-Daten auf Aktualität und, falls erforderlich, des Abrufens neuer Daten zur Aktualisierung des Caches.
 - Statisches Rendering (SSG - Static Site Generation): Seiten werden zur Build-Zeit vorgerendert, was zu statischen HTML-Dateien führt, die direkt von einem CDN ausgeliefert werden. Diese Seiten werden bis zu einem neuen Build naturgemäß zwischengespeichert.
 - Dynamisches Rendering (SSR - Server-Side Rendering): Seiten werden zur Laufzeit der Anfrage auf dem Server gerendert. Dies ermöglicht das dynamische Abrufen von Daten, aber der Server kann die Ergebnisse interner 
fetch-Aufrufe immer noch zwischenspeichern. - Server Component: Ein neues Paradigma in React (und Next.js App Router) für das Rendern von Komponenten direkt auf dem Server, was potenziell JavaScript auf der Client-Seite reduziert und die anfängliche Seitenladezeit verbessert. Diese Komponenten können Daten direkt abrufen (
fetch). - Data Cache: Ein Speichermechanismus (oft im Speicher oder auf der Festplatte), der von Next.js verwendet wird, um die Ergebnisse von 
fetch-Anfragen zu speichern, die auf dem Server durchgeführt werden. - Full Route Cache: Ein Cache, der die vollständige HTML-Nutzlast einer gerenderten Route speichert und darunter den Data Cache nutzt.
 
Data-Caching und Revalidierungsstrategie des Next.js App Routers
Der Next.js App Router führt ein hochgradig ausgeklügeltes und meinungsbasiertes Caching-System ein. Im Kern speichert es intelligent Datenanfragen, die innerhalb von Server Components und anderen serverseitigen Kontexten erfolgen. Dieses Caching ist nicht nur ein einfacher Schlüssel-Wert-Speicher; es ist tief in den Rendering-Lebenszyklus integriert und basiert auf der fetch-API des Webs.
Standardmäßig wird davon ausgegangen, dass fetch-Anfragen innerhalb von Server Components zwischengespeichert werden können. Wenn eine fetch-Anfrage mit der Standardoption cache: 'force-cache' gestellt wird (was der Standard ist, wenn sie nicht angegeben wird), speichert Next.js die Antwort in seinem Data Cache. Nachfolgende identische fetch-Anfragen (gleiche URL, gleiche Optionen) werden dann aus diesem Cache bedient, was die Datenabfrage erheblich beschleunigt.
Lassen Sie uns dies anhand eines Beispiels veranschaulichen:
// app/page.tsx async function getPosts() { const res = await fetch('https://jsonplaceholder.typicode.com/posts'); // Die Option 'cache: "force-cache"' ist hier implizit if (!res.ok) { throw new Error('Failed to fetch data'); } return res.json(); } export default async function Page() { const posts = await getPosts(); return ( <div> <h1>Posts</h1> <ul> {posts.map((post: any) => ( <li key={post.id}>{post.title}</li> ))} </ul> </div> ); }
In diesem Szenario ruft getPosts() Daten von der API ab. Wenn diese Route zum ersten Mal gerendert wird, führt Next.js den tatsächlichen API-Aufruf durch und speichert die Antwort. Wenn der Benutzer diese Seite innerhalb kurzer Zeit erneut aufruft oder wenn die Serverkomponente neu gerendert wird (z. B. aufgrund eines anderen Benutzers, die Daten aber gemeinsam genutzt werden), liefert Next.js die Daten direkt aus seinem Data Cache, ohne einen weiteren Netzwerkaufruf an jsonplaceholder.typicode.com zu tätigen.
Wann wird der Cache ungültig gemacht oder revalidiert?
Hier glänzt die Flexibilität von Next.js. Es gibt mehrere Möglichkeiten, die Revalidierung zu verwalten:
- 
Zeitbasierte Revalidierung (
next.revalidate): Sie können Next.js mitteilen, den Cache für eine bestimmtefetch-Anfrage nach einer bestimmten Zeit mithilfe der Optionnext.revalidateneu zu validieren.async function getPosts() { const res = await fetch('https://jsonplaceholder.typicode.com/posts', { next: { revalidate: 60 }, // Alle 60 Sekunden neu validieren }); if (!res.ok) { throw new Error('Failed to fetch data'); } return res.json(); }Mit
revalidate: 60wird nach 60 Sekunden nach dem Caching der Daten die nächste Anfrage eine Hintergrund-Revalidierung auslösen. Die veralteten Daten werden sofort geliefert, und Next.js ruft die neuen Daten leise im Hintergrund ab, um den Cache für nachfolgende Anfragen zu aktualisieren. - 
Explizite Cache-Invalidierung (
cache: 'no-store'): Wenn Sie auf keinen Fall möchten, dass einefetch-Anfrage zwischengespeichert wird, können Sie sich explizit abmelden:async function getLiveStockPrices() { const res = await fetch('https://api.example.com/stock-prices', { cache: 'no-store', // Immer frische Daten abrufen }); if (!res.ok) { throw new Error('Failed to fetch data'); } return res.json(); }Dies ist ideal für hochdynamische Daten, die sich häufig ändern und bei denen die Anzeige veralteter Daten nicht akzeptabel ist (z. B. Echtzeit-Börsenkurse, benutzerspezifische Einkaufswageninhalte).
 - 
Caching für ein Routensegment deaktivieren: Sie können ein gesamtes Routensegment als dynamisch konfigurieren, was bedeutet, dass alle
fetch-Anfragen innerhalb dieses Segments standardmäßigno-storeverwenden und die Route selbst dynamisch gerendert wird. Dies geschieht durch Exportieren einerdynamic-Option aus einerlayout.tsx- oderpage.tsx-Datei:// app/dashboard/page.tsx oder app/dashboard/layout.tsx export const dynamic = 'force-dynamic'; // Dies führt dazu, dass alle Fetches in diesem Segment wie 'no-store' agierenAndere Optionen sind
'auto'(Standard),'error'und'force-static'. Das Setzen vondynamic = 'force-dynamic'ist eine leistungsstarke Methode, um die Aktualität eines ganzen Teils Ihrer Anwendung sicherzustellen. - 
On-Demand-Revalidierung (
revalidatePath,revalidateTag): Für Daten, die sich aufgrund externer Ereignisse ändern (z. B. CMS-Update, E-Commerce-Bestellung), können Sie die Revalidierung programmgesteuert auslösen.revalidatePath(path: string): Revalidiert den Daten-Cache für einen bestimmten Pfad.revalidateTag(tag: string): Revalidiert allefetch-Anfragen, die mit einem bestimmten String getaggt wurden.
Um
revalidateTagzu verwenden, müssen Sie Ihre Fetch-Anfragen taggen:// app/products/page.tsx async function getProducts() { const res = await fetch('https://api.example.com/products', { next: { tags: ['products'] }, // Diese Fetch-Anfrage taggen }); if (!res.ok) { throw new Error('Failed to fetch products'); } return res.json(); } // api/revalidate-products.ts (eine API-Route zum Auslösen der Revalidierung) import { NextRequest, NextResponse } from 'next/server'; import { revalidateTag } from 'next/cache'; export async function GET(request: NextRequest) { const tag = request.nextUrl.searchParams.get('tag'); // z.B. ?tag=products if (tag) { revalidateTag(tag); return NextResponse.json({ revalidated: true, now: Date.now() }); } return NextResponse.json({ revalidated: false, message: 'Missing tag' }); }Dies ermöglicht es Ihnen, Webhooks oder Admin-Oberflächen zu erstellen, um bestimmte Cache-Einträge programmgesteuert zu löschen und sofortige Aktualisierungen zu ermöglichen, ohne Ihre gesamte Anwendung neu erstellen zu müssen.
 
Auslöser für die Cache-Invalidierung verstehen
Es ist wichtig, die Auslöser für die Data-Cache-Invalidierung von Next.js zu beachten:
- Deployment: Eine neue Bereitstellung Ihrer Next.js-Anwendung löscht alle Daten-Caches.
 next.revalidateüberschreitet seine Zeit: Wie bereits erwähnt, führt dies zu einer Hintergrundrevalidierung.- On-Demand-Revalidierung: 
revalidatePathoderrevalidateTagwerden explizit aufgerufen. - Entwicklungsmodus: Im Entwicklungsmodus (
npm run dev) führt Next.js im Allgemeinen weniger aggressive Caching-Maßnahmen durch, um sicherzustellen, dass Sie immer sofort die neuesten Änderungen sehen. Möglicherweise beobachten Sie nicht dasselbe Caching-Verhalten wie in der Produktion. 
Fazit
Das Rätsel „Warum wird mein Fetch zwischengespeichert?“ im Next.js App Router ist ein Beweis für seine leistungsstarken, aber manchmal unsichtbaren Optimierungsstrategien. Durch das Verständnis des Standard-Caching-Verhaltens von fetch innerhalb von Server Components und die Beherrschung der Tools zur Revalidierung wie next.revalidate, cache: 'no-store', export const dynamic und On-Demand-Revalidierungsfunktionen können Entwickler die Aktualität der Daten präzise steuern und hochperformante Benutzererlebnisse liefern. Die effektive Nutzung der Data-Caching- und Revalidierungsmechanismen von Next.js ist der Schlüssel zum Aufbau schneller, dynamischer und zuverlässiger Webanwendungen.