Implementierung von Incremental Static Regeneration (ISR)
Beispiele
Incremental Static Regeneration (ISR) ermöglicht Ihnen:
- Statische Inhalte ohne Neubau der gesamten Website zu aktualisieren
- Serverlast zu reduzieren durch Ausliefern vorgerenderter, statischer Seiten für die meisten Anfragen
- Sicherzustellen, dass korrekte
cache-control
-Header automatisch zu Seiten hinzugefügt werden - Große Mengen von Inhaltsseiten ohne lange
next build
-Zeiten zu verwalten
Hier ist ein minimales Beispiel:
import type { GetStaticPaths, GetStaticProps } from 'next'
interface Post {
id: string
title: string
content: string
}
interface Props {
post: Post
}
export const getStaticPaths: GetStaticPaths = async () => {
const posts = await fetch('https://api.vercel.app/blog').then((res) =>
res.json()
)
const paths = posts.map((post: Post) => ({
params: { id: String(post.id) },
}))
// Wir werden nur diese Pfade zur Build-Zeit vorrendern.
// { fallback: 'blocking' } wird Seiten bedarfsgerecht
// serverseitig rendern, wenn der Pfad nicht existiert.
return { paths, fallback: false }
}
export const getStaticProps: GetStaticProps<Props> = async ({
params,
}: {
params: { id: string }
}) => {
const post = await fetch(`https://api.vercel.app/blog/${params.id}`).then(
(res) => res.json()
)
return {
props: { post },
// Next.js wird den Cache ungültig machen, wenn eine
// Anfrage eingeht, maximal einmal alle 60 Sekunden.
revalidate: 60,
}
}
export default function Page({ post }: Props) {
return (
<main>
<h1>{post.title}</h1>
<p>{post.content}</p>
</main>
)
}
export async function getStaticPaths() {
const posts = await fetch('https://api.vercel.app/blog').then((res) =>
res.json()
)
const paths = posts.map((post) => ({
params: { id: post.id },
}))
// Wir werden nur diese Pfade zur Build-Zeit vorrendern.
// { fallback: false } bedeutet, dass andere Routen 404 zurückgeben sollten.
return { paths, fallback: false }
}
export async function getStaticProps({ params }) {
const post = await fetch(`https://api.vercel.app/blog/${params.id}`).then(
(res) => res.json()
)
return {
props: { post },
// Next.js wird den Cache ungültig machen, wenn eine
// Anfrage eingeht, maximal einmal alle 60 Sekunden.
revalidate: 60,
}
}
export default function Page({ post }) {
return (
<main>
<h1>{post.title}</h1>
<p>{post.content}</p>
</main>
)
}
So funktioniert dieses Beispiel:
- Während
next build
werden alle bekannten Blogbeiträge generiert (in diesem Beispiel gibt es 25) - Alle Anfragen an diese Seiten (z.B.
/blog/1
) werden zwischengespeichert und sind sofort verfügbar - Nach 60 Sekunden zeigt die nächste Anfrage weiterhin die zwischengespeicherte (veraltete) Seite
- Der Cache wird ungültig gemacht und eine neue Version der Seite beginnt im Hintergrund zu generieren
- Nach erfolgreicher Generierung zeigt Next.js die aktualisierte Seite an und speichert sie im Cache
- Wenn
/blog/26
angefragt wird, generiert Next.js diese Seite bedarfsgerecht und speichert sie im Cache
Referenz
Funktionen
Beispiele
On-Demand-Validierung mit res.revalidate()
Für eine präzisere Methode der Revalidierung können Sie res.revalidate
verwenden, um eine neue Seite bedarfsgerecht von einem API-Router aus zu generieren.
Zum Beispiel kann diese API-Route unter /api/revalidate?secret=<token>
aufgerufen werden, um einen bestimmten Blogbeitrag zu revalidieren. Erstellen Sie ein geheimes Token, das nur Ihrer Next.js-App bekannt ist. Dieses Geheimnis wird verwendet, um unbefugten Zugriff auf die Revalidierungs-API-Route zu verhindern.
import type { NextApiRequest, NextApiResponse } from 'next'
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
// Überprüfen des Geheimnisses, um sicherzustellen, dass dies eine gültige Anfrage ist
if (req.query.secret !== process.env.MY_SECRET_TOKEN) {
return res.status(401).json({ message: 'Ungültiges Token' })
}
try {
// Dies sollte der tatsächliche Pfad sein, kein umgeschriebener Pfad
// z.B. für "/posts/[id]" sollte dies "/posts/1" sein
await res.revalidate('/posts/1')
return res.json({ revalidated: true })
} catch (err) {
// Bei einem Fehler zeigt Next.js weiterhin
// die letzte erfolgreich generierte Seite an
return res.status(500).send('Fehler bei der Revalidierung')
}
}
export default async function handler(req, res) {
// Überprüfen des Geheimnisses, um sicherzustellen, dass dies eine gültige Anfrage ist
if (req.query.secret !== process.env.MY_SECRET_TOKEN) {
return res.status(401).json({ message: 'Ungültiges Token' })
}
try {
// Dies sollte der tatsächliche Pfad sein, kein umgeschriebener Pfad
// z.B. für "/posts/[id]" sollte dies "/posts/1" sein
await res.revalidate('/posts/1')
return res.json({ revalidated: true })
} catch (err) {
// Bei einem Fehler zeigt Next.js weiterhin
// die letzte erfolgreich generierte Seite an
return res.status(500).send('Fehler bei der Revalidierung')
}
}
Wenn Sie On-Demand-Revalidierung verwenden, müssen Sie keine revalidate
-Zeit in getStaticProps
angeben. Next.js verwendet den Standardwert false
(keine Revalidierung) und revalidiert die Seite nur bedarfsgerecht, wenn res.revalidate()
aufgerufen wird.
Behandlung unbehandelter Ausnahmen
Wenn ein Fehler in getStaticProps
während der Hintergrundregenerierung auftritt oder Sie manuell einen Fehler werfen, wird die zuletzt erfolgreich generierte Seite weiterhin angezeigt. Bei der nächsten nachfolgenden Anfrage wird Next.js erneut versuchen, getStaticProps
aufzurufen.
import type { GetStaticProps } from 'next'
interface Post {
id: string
title: string
content: string
}
interface Props {
post: Post
}
export const getStaticProps: GetStaticProps<Props> = async ({
params,
}: {
params: { id: string }
}) => {
// Wenn diese Anfrage einen unbehandelten Fehler wirft, wird Next.js
// die aktuell angezeigte Seite nicht ungültig machen und
// getStaticProps bei der nächsten Anfrage erneut aufrufen.
const res = await fetch(`https://api.vercel.app/blog/${params.id}`)
const post: Post = await res.json()
if (!res.ok) {
// Bei einem Serverfehler sollten Sie möglicherweise
// einen Fehler werfen statt zurückzugeben, damit der Cache nicht aktualisiert wird
// bis zur nächsten erfolgreichen Anfrage.
throw new Error(`Fehler beim Abrufen der Beiträge, Status ${res.status}`)
}
return {
props: { post },
// Next.js wird den Cache ungültig machen, wenn eine
// Anfrage eingeht, maximal einmal alle 60 Sekunden.
revalidate: 60,
}
}
export async function getStaticProps({ params }) {
// Wenn diese Anfrage einen unbehandelten Fehler wirft, wird Next.js
// die aktuell angezeigte Seite nicht ungültig machen und
// getStaticProps bei der nächsten Anfrage erneut aufrufen.
const res = await fetch(`https://api.vercel.app/blog/${params.id}`)
const post = await res.json()
if (!res.ok) {
// Bei einem Serverfehler sollten Sie möglicherweise
// einen Fehler werfen statt zurückzugeben, damit der Cache nicht aktualisiert wird
// bis zur nächsten erfolgreichen Anfrage.
throw new Error(`Fehler beim Abrufen der Beiträge, Status ${res.status}`)
}
return {
props: { post },
// Next.js wird den Cache ungültig machen, wenn eine
// Anfrage eingeht, maximal einmal alle 60 Sekunden.
revalidate: 60,
}
}
Anpassung des Cache-Speicherorts
Sie können den Cache-Speicherort von Next.js konfigurieren, wenn Sie zwischengespeicherte Seiten und Daten in dauerhaften Speicher persistieren oder den Cache über mehrere Container oder Instanzen Ihrer Next.js-Anwendung hinweg teilen möchten. Mehr erfahren.
Problembehandlung
Debuggen von zwischengespeicherten Daten in der lokalen Entwicklung
Wenn Sie die fetch
-API verwenden, können Sie zusätzliche Protokollierung hinzufügen, um zu verstehen, welche Anfragen zwischengespeichert oder nicht zwischengespeichert sind. Mehr über die logging
-Option erfahren.
module.exports = {
logging: {
fetches: {
fullUrl: true,
},
},
}
Überprüfung des korrekten Produktionsverhaltens
Um zu überprüfen, ob Ihre Seiten in der Produktion korrekt zwischengespeichert und revalidiert werden, können Sie lokal testen, indem Sie next build
und dann next start
ausführen, um den Next.js-Produktionsserver zu starten.
Dadurch können Sie das ISR-Verhalten (Incremental Static Regeneration) testen, wie es in einer Produktionsumgebung funktionieren würde. Für weitere Debugging-Zwecke fügen Sie die folgende Umgebungsvariable zu Ihrer .env
-Datei hinzu:
NEXT_PRIVATE_DEBUG_CACHE=1
Dies führt dazu, dass der Next.js-Server ISR-Cache-Treffer und -Fehlschläge in der Konsole protokolliert. Sie können die Ausgabe untersuchen, um zu sehen, welche Seiten während next build
generiert werden und wie Seiten aktualisiert werden, wenn Pfade bedarfsgesteuert aufgerufen werden.
Einschränkungen
- ISR wird nur unterstützt, wenn die Node.js-Laufzeitumgebung (Standard) verwendet wird.
- ISR wird nicht unterstützt, wenn ein Statischer Export erstellt wird.
- Middleware wird nicht für bedarfsgesteuerte ISR-Anfragen ausgeführt, was bedeutet, dass Pfadumleitungen oder Logik in der Middleware nicht angewendet werden. Stellen Sie sicher, dass Sie den exakten Pfad revalidieren. Zum Beispiel
/post/1
anstelle eines umgeleiteten/post-1
.
Plattformunterstützung
Bereitstellungsoption | Unterstützt |
---|---|
Node.js-Server | Ja |
Docker-Container | Ja |
Statischer Export | Nein |
Adapter | Plattformabhängig |
Erfahren Sie, wie Sie ISR konfigurieren, wenn Sie Next.js selbst hosten.
Versionsverlauf
Version | Änderungen |
---|---|
v14.1.0 | Benutzerdefinierter cacheHandler ist stabil. |
v13.0.0 | App Router wird eingeführt. |
v12.2.0 | Pages Router: On-Demand ISR ist stabil |
v12.0.0 | Pages Router: Bot-aware ISR-Fallback hinzugefügt. |
v9.5.0 | Pages Router: Stabiles ISR eingeführt. |