Hirefullstack – Software Engineering & IT-Beratung aus Berlin
← Zur Übersicht
Kern 16 Min Lesezeit

Caching verstehen

Warum die Seite nach dem Deploy plötzlich eingefroren ist

Baut auf: Daten laden
In einem Satz

Next.js speichert an vier Stellen zwischen. Fast alle Überraschungen kommen daher, dass man nicht weiß, welche davon gerade zuschlägt.

Das ist die Lektion, an der die meisten hängenbleiben – und der Grund, warum Next.js den Ruf hat, „unvorhersehbar“ zu sein. Es ist aber vorhersehbar, sobald man die vier Speicher auseinanderhalten kann.

Achtung Zum Ausprobieren brauchst du einen echten Build

Im Entwicklungsmodus ist fast nichts zwischengespeichert. Wer Caching untersucht, muss npm run build && npm run start benutzen – sonst sieht man das Verhalten schlicht nicht.

Die vier Speicher

uebersicht.txt
1. Request Memoization   während EINES Seitenaufbaus
   Derselbe fetch zweimal? Läuft trotzdem nur einmal.

2. Data Cache            über Anfragen und Deploys hinweg
   Antworten von fetch, bis du sie für ungültig erklärst.

3. Full Route Cache      das fertige HTML statischer Seiten
   Entsteht beim Bauen, wird danach direkt ausgeliefert.

4. Router Cache          im Browser des Nutzers
   Kürzlich besuchte Seiten, damit "zurück" sofort geht.
Bildlich gesprochen

Wie in einer Küche: Die Zutatenlieferung kommt nicht für jedes Gericht neu (Data CacheNext.js merkt sich Antworten von `fetch` über Anfragen und Deploys hinweg, bis du sie für ungültig erklärst.). Ein Gericht, das immer gleich ist, wird vorgekocht (Full Route CacheDas fertig gerenderte HTML einer statischen Seite, das beim Bauen entsteht und danach direkt ausgeliefert wird.). Und was der Gast eben schon auf dem Tisch hatte, muss nicht neu angerichtet werden (Router CacheDer Zwischenspeicher im Browser: Beim Zurücknavigieren zeigt Next.js die Seite sofort aus dem Speicher.).

Der wichtigste: statisch oder dynamisch

Die größte Wirkung hat die Frage, ob eine Seite beim Bauen einmal entsteht (Statisches RendernDie Seite wird schon beim Bauen erzeugt und danach für alle gleich ausgeliefert. Schnell und billig – der Standard, wo möglich.) oder bei jeder Anfrage neu (Dynamisches RendernDie Seite wird bei jeder Anfrage neu erzeugt. Nötig, sobald sie von Cookies, Kopfzeilen oder Suchparametern abhängt.). Next.js entscheidet das selbst – anhand dessen, was du benutzt.

entscheidung.txt
Statisch bleibt die Seite, solange du nichts davon anfasst.

Dynamisch wird sie, sobald du benutzt:
  • cookies()
  • headers()
  • searchParams
  • fetch(..., { cache: "no-store" })
  • export const dynamic = "force-dynamic"
Stolperstein Ein einziges cookies() genügt

Diese Dynamische Funktionen`cookies()`, `headers()` und `searchParams`. Sobald du eine benutzt, kann die Seite nicht mehr statisch sein. färben ab: Sobald irgendwo im Baum eine davon vorkommt, kann die ganze Seite nicht mehr statisch sein. Deshalb schiebt man sie so tief wie möglich – oder kapselt sie in ein <Suspense>, damit nur dieser Teil dynamisch wird.

Wie lange gelten geholte Daten?

fetch-optionen.tsx
// Standard: gespeichert, bis du es für ungültig erklärst
await fetch(url);

// Nie speichern – jede Anfrage holt frisch (macht die Seite dynamisch)
await fetch(url, { cache: "no-store" });

// Höchstens 60 Sekunden alt
await fetch(url, { next: { revalidate: 60 } });

// Mit Etikett, um es später gezielt für ungültig zu erklären
await fetch(url, { next: { tags: ["artikel"] } });
app/blog/page.tsx
// Gilt für die ganze Seite statt pro fetch:
export const revalidate = 3600;      // stündlich neu bauen
export const dynamic = "force-dynamic";  // immer frisch
export const dynamic = "force-static";   // immer statisch
Diese Exporte stehen in der page.tsx oder layout.tsx und wirken auf alles darunter.
Gut zu wissen Die Voreinstellung hat sich geändert

In frühen Versionen des App Routers war fetch immer zwischengespeichert, was viele überrascht hat. Seit Next.js 15 ist der Standard zurückhaltender. Wenn du einer älteren Anleitung folgst, prüfe die Version – dieser Punkt ist genau der, an dem sich alte und neue Beispiele widersprechen.

Was du wann brauchst

Nimm es, wenn …
  • +

    Statisch: Marketingseiten, Blog, Dokumentation, Produktkatalog

  • +

    revalidate: Inhalte, die aktuell sein sollen, aber nicht sekundengenau

  • +

    Dynamisch: alles Persönliche – Konto, Warenkorb, Dashboard

Lass es, wenn …
  • no-store als Reflex – damit verschenkst du den größten Vorteil

  • force-dynamic auf der ganzen Seite, obwohl nur ein Teil persönlich ist

  • Caching-Fragen im Entwicklungsmodus untersuchen

Genauer erklärt: Fehlersuche bei Caching-Problemen optional

Wenn eine Seite falsche Daten zeigt, hilft diese Reihenfolge – von außen nach innen:

vorgehen.txt
1. Ist die Seite überhaupt statisch?
   npm run build zeigt es an:
     ○  statisch      ← wird beim Bauen erzeugt
     ƒ  dynamisch     ← bei jeder Anfrage

2. Zeigt ein harter Reload (Strg+Shift+R) frische Daten?
   → dann war es der Router Cache im Browser.

3. Zeigt ein neuer Build frische Daten?
   → dann war es der Full Route Cache: du brauchst revalidate.

4. Auch danach alt?
   → dann hängt es am Data Cache: revalidateTag oder no-store.
Tipp Die Bauausgabe ist dein bester Freund

npm run build listet jede Adresse mit einem Symbol davor. Wenn dort ein steht, wo du ƒ erwartet hast, hast du die Ursache schon gefunden – ohne eine Zeile Code zu lesen.

Sitzt das schon?

5 Fragen zu dieser Lektion. Falsche Antworten landen in deiner Statistik.

Hirefullstack

Ihr braucht React-Verstärkung im Team?

Wir bauen seit Jahren React- und Next.js-Anwendungen für Kunden in ganz Deutschland – als einzelner Experte, als Verstärkung fürs Bestandsteam oder als komplettes Scrum-Team.

Projekt besprechen →