Menu

Inkrementelle Statische Regenerierung (ISR)

Beispiele

Mit Inkrementeller Statischer Regenerierung (ISR) kannst du:

  • Statische Inhalte aktualisieren, ohne die gesamte Website neu zu erstellen
  • Die Serverlast reduzieren, indem vorgerenderte, statische Seiten für die meisten Anfragen bereitgestellt werden
  • Sicherstellen, dass korrekte cache-control Header automatisch zu den Seiten hinzugefügt werden
  • Große Mengen an Inhaltsseiten verwalten, ohne lange next build Zeiten

Hier ist ein minimales Beispiel:

app/blog/[id]/page.tsx
TypeScript
interface Post {
  id: string
  title: string
  content: string  
}
 
// Next.js wird den Cache invalidieren, wenn eine
// Anfrage eingeht, höchstens alle 60 Sekunden.
export const revalidate = 60
 
// Wir werden nur die Parameter aus `generateStaticParams` zur Build-Zeit vorrendern.
// Wenn eine Anfrage für einen nicht generierten Pfad eingeht,
// wird Next.js die Seite bei Bedarf server-seitig rendern.
export const dynamicParams = true // oder false für 404 bei unbekannten Pfaden
 
export async function generateStaticParams() {
  const posts: Post[] = await fetch('https://api.vercel.app/blog').then((res) =>
    res.json()
  )
  return posts.map((post) => ({
    id: String(post.id),
  }))
}
 
export default async function Page({ params }: { params: { id: string } }) {
  const post: Post = await fetch(
    `https://api.vercel.app/blog/${params.id}`
  ).then((res) => res.json())
  return (
    <main>
      <h1>{post.title}</h1>
      <p>{post.content}</p>
    </main>
  )
}

So funktioniert dieses Beispiel:

  1. Während next build werden alle bekannten Blogbeiträge generiert (in diesem Beispiel sind es 25)
  2. Alle Anfragen an diese Seiten (z.B. /blog/1) werden gecached und sind sofort verfügbar
  3. Nach Ablauf von 60 Sekunden zeigt die nächste Anfrage weiterhin die gecachte (veraltete) Seite
  4. Der Cache wird invalidiert und eine neue Version der Seite wird im Hintergrund generiert
  5. Nach erfolgreicher Generierung zeigt Next.js die aktualisierte Seite und speichert sie im Cache
  6. Wenn /blog/26 angefragt wird, generiert Next.js diese Seite bei Bedarf und speichert sie im Cache

Referenz

Route Segment Konfiguration

Funktionen

Beispiele

Zeit-basierte Revalidierung

Dies lädt und zeigt eine Liste von Blogbeiträgen unter /blog. Nach einer Stunde wird der Cache für diese Seite bei der nächsten Anfrage invalidiert. Dann wird im Hintergrund eine neue Version der Seite mit den aktuellsten Blogbeiträgen generiert.

app/blog/page.tsx
TypeScript
interface Post {
  id: string
  title: string
  content: string
}
 
export const revalidate = 3600 // jede Stunde invalidieren
 
export default async function Page() {
  const data = await fetch('https://api.vercel.app/blog')
  const posts: Post[] = await data.json()
  return (
    <main>
      <h1>Blog Beiträge</h1>
      <ul>
        {posts.map((post) => (
          <li key={post.id}>{post.title}</li>
        ))}
      </ul>
    </main>
  )
}

Wir empfehlen eine lange Revalidierungszeit einzustellen. Zum Beispiel 1 Stunde statt 1 Sekunde. Wenn du mehr Präzision benötigst, solltest du On-Demand Revalidierung in Betracht ziehen. Wenn du Echtzeitdaten benötigst, solltest du zu dynamischem Rendering wechseln.

On-Demand Revalidierung mit revalidatePath

Für eine präzisere Revalidierungsmethode kannst du Seiten bei Bedarf mit der revalidatePath Funktion invalidieren.

Diese Server Action würde zum Beispiel nach dem Hinzufügen eines neuen Beitrags aufgerufen werden. Unabhängig davon, wie du deine Daten in deiner Server Komponente abrufst, sei es mit fetch oder einer Datenbankverbindung, wird dies den Cache für die gesamte Route löschen und der Server Komponente ermöglichen, neue Daten abzurufen.

app/actions.ts
'use server'
 
import { revalidatePath } from 'next/cache'
 
export async function createPost() {
  // Den Cache für die /posts Route invalidieren
  revalidatePath('/posts')
}
app/actions.js
'use server'
 
import { revalidatePath } from 'next/cache'
 
export async function createPost() {
  // Den Cache für die /posts Route invalidieren  
  revalidatePath('/posts')
}

Demo ansehen und Quellcode durchsuchen.

On-Demand Revalidierung mit revalidateTag

Für die meisten Anwendungsfälle ist es besser, ganze Pfade zu revalidieren. Wenn du mehr Kontrolle benötigst, kannst du die revalidateTag Funktion verwenden. Du kannst zum Beispiel einzelne fetch Aufrufe taggen:

app/blog/page.tsx
TypeScript
export default async function Page() {
  const data = await fetch('https://api.vercel.app/blog', {
    next: { tags: ['posts'] },
  })
  const posts = await data.json()
  // ...
}

Wenn du ein ORM verwendest oder dich mit einer Datenbank verbindest, kannst du unstable_cache verwenden:

app/blog/page.tsx
TypeScript
import { unstable_cache } from 'next/cache'
import { db, posts } from '@/lib/db'
 
const getCachedPosts = unstable_cache(
  async () => {
    return await db.select().from(posts)
  },
  ['posts'],
  { revalidate: 3600, tags: ['posts'] }
)
 
export default async function Page() {
  const posts = getCachedPosts()
  // ...
}

Du kannst dann revalidateTag in einer Server Action oder einem Route Handler verwenden:

app/actions.ts
'use server'
 
import { revalidateTag } from 'next/cache'
 
export async function createPost() {
  // Alle Daten mit dem Tag 'posts' im Cache invalidieren
  revalidateTag('posts')
}
app/actions.js
'use server'
 
import { revalidateTag } from 'next/cache'
 
export async function createPost() {
  // Alle Daten mit dem Tag 'posts' im Cache invalidieren
  revalidateTag('posts')
}

Umgang mit nicht abgefangenen Ausnahmen

Wenn beim Versuch der Datenrevalidierung ein Fehler auftritt, werden die zuletzt erfolgreich generierten Daten weiterhin aus dem Cache bereitgestellt. Bei der nächsten Anfrage wird Next.js versuchen, die Daten erneut zu revalidieren. Mehr über Fehlerbehandlung.

Anpassen des Cache-Speicherorts

Caching und Revalidierung von Seiten (mit Inkrementeller Statischer Regenerierung) verwenden denselben gemeinsamen Cache. Bei Deployment auf Vercel wird der ISR-Cache automatisch in dauerhaftem Speicher persistiert.

Bei Self-Hosting wird der ISR-Cache im Dateisystem (auf der Festplatte) deines Next.js-Servers gespeichert. Dies funktioniert automatisch beim Self-Hosting sowohl mit dem Pages als auch dem App Router.

Du kannst den Next.js Cache-Speicherort konfigurieren, wenn du gecachte Seiten und Daten in dauerhaftem Speicher persistieren oder den Cache über mehrere Container oder Instanzen deiner Next.js Anwendung hinweg teilen möchtest. Mehr erfahren.

Fehlerbehebung

Debugging von Cache-Daten in lokaler Entwicklung

Wenn du die fetch API verwendest, kannst du zusätzliches Logging hinzufügen, um zu verstehen, welche Anfragen gecached oder nicht gecached sind. Mehr über die logging Option.

next.config.js
module.exports = {
  logging: {
    fetches: {
      fullUrl: true,
    },
  },
}

Überprüfen des korrekten Produktionsverhaltens

Um zu überprüfen, ob deine Seiten im Produktionsmodus korrekt gecached und revalidiert werden, kannst du lokal testen, indem du next build und dann next start ausführst, um den Next.js Produktionsserver zu starten.

Dies ermöglicht es dir, das ISR-Verhalten so zu testen, wie es in einer Produktionsumgebung funktionieren würde. Für weitere Debugging-Möglichkeiten füge die folgende Umgebungsvariable zu deiner .env Datei hinzu:

.env
NEXT_PRIVATE_DEBUG_CACHE=1

Dies wird den Next.js Server dazu veranlassen, ISR Cache-Treffer und -Fehltreffer in der Konsole zu protokollieren. Du kannst die Ausgabe überprüfen, um zu sehen, welche Seiten während next build generiert werden, sowie wie Seiten aktualisiert werden, wenn Pfade bei Bedarf aufgerufen werden.

Einschränkungen

  • ISR wird nur bei Verwendung der Node.js Runtime (Standard) unterstützt.
  • ISR wird nicht beim Erstellen eines Statischen Exports unterstützt.
  • Wenn du mehrere fetch-Anfragen in einer statisch gerenderten Route hast und jede eine andere revalidate-Häufigkeit hat, wird die kürzeste Zeit für ISR verwendet. Diese Revalidierungshäufigkeiten werden jedoch vom Daten-Cache weiterhin respektiert.
  • Wenn eine der fetch-Anfragen, die auf einer Route verwendet werden, eine revalidate-Zeit von 0 oder ein explizites no-store hat, wird die Route dynamisch gerendert.
  • Middleware wird nicht für On-Demand ISR-Anfragen ausgeführt, das bedeutet, dass Pfadumschreibungen oder Logik in Middleware nicht angewendet werden. Stelle sicher, dass du den exakten Pfad revalidierst. Zum Beispiel /post/1 anstelle eines umgeschriebenen /post-1.

Versionshistorie

VersionÄnderungen
v14.1.0Custom cacheHandler ist stabil.
v13.0.0App Router wird eingeführt.
v12.2.0Pages Router: On-Demand ISR ist stabil
v12.0.0Pages Router: Bot-bewusster ISR Fallback hinzugefügt.
v9.5.0Pages Router: Stabiles ISR eingeführt.