Draft Mode (Entwurfsmodus)
Statisches Rendering ist nützlich, wenn Ihre Seiten Daten von einem Headless CMS abrufen. Es ist jedoch nicht ideal, wenn Sie einen Entwurf in Ihrem Headless CMS schreiben und diesen sofort auf Ihrer Seite anzeigen möchten. In diesem Fall sollten Sie Next.js dazu bringen, diese Seiten zur Laufzeit (request time) statt zur Build-Zeit zu rendern und den Entwurfsinhalt statt des veröffentlichten Inhalts abzurufen. Sie möchten, dass Next.js nur für diesen speziellen Fall auf dynamisches Rendering umschaltet.
Next.js bietet eine Funktion namens Draft Mode (Entwurfsmodus), die dieses Problem löst. Hier finden Sie Anweisungen zur Verwendung.
Schritt 1: Route Handler erstellen und aufrufen
Erstellen Sie zunächst einen Route Handler. Er kann beliebig benannt werden, z.B. app/api/draft/route.ts
.
Importieren Sie dann draftMode
aus next/headers
und rufen Sie die Methode enable()
auf.
// Route Handler zur Aktivierung des Draft Mode
import { draftMode } from 'next/headers'
export async function GET(request: Request) {
draftMode().enable()
return new Response('Draft mode is enabled')
}
// Route Handler zur Aktivierung des Draft Mode
import { draftMode } from 'next/headers'
export async function GET(request) {
draftMode().enable()
return new Response('Draft mode is enabled')
}
Dadurch wird ein Cookie gesetzt, um den Draft Mode zu aktivieren. Nachfolgende Anfragen mit diesem Cookie lösen den Draft Mode aus und ändern das Verhalten für statisch generierte Seiten (mehr dazu später).
Sie können dies manuell testen, indem Sie /api/draft
aufrufen und die Entwicklertools Ihres Browsers überprüfen. Beachten Sie den Set-Cookie
-Response-Header mit einem Cookie namens __prerender_bypass
.
Sicherer Zugriff von Ihrem Headless CMS
In der Praxis sollten Sie diesen Route Handler sicher von Ihrem Headless CMS aus aufrufen. Die genauen Schritte hängen von Ihrem Headless CMS ab, aber hier sind einige allgemeine Schritte:
Diese Schritte setzen voraus, dass Ihr Headless CMS das Setzen von benutzerdefinierten Entwurfs-URLs unterstützt. Falls nicht, können Sie diese Methode dennoch verwenden, um Ihre Entwurfs-URLs zu sichern, müssen die URL jedoch manuell erstellen und aufrufen.
Erstens sollten Sie ein geheimes Token mit einem Token-Generator Ihrer Wahl erstellen. Dieses Geheimnis sollte nur Ihrer Next.js-App und Ihrem Headless CMS bekannt sein. Es verhindert, dass Personen ohne CMS-Zugriff auf Entwurfs-URLs zugreifen können.
Zweitens, wenn Ihr Headless CMS benutzerdefinierte Entwurfs-URLs unterstützt, geben Sie folgende URL als Entwurfs-URL an. Hier wird angenommen, dass Ihr Route Handler unter app/api/draft/route.ts
liegt.
https://<your-site>/api/draft?secret=<token>&slug=<path>
<your-site>
sollte Ihre Bereitstellungsdomain sein.<token>
sollte durch Ihr geheimes Token ersetzt werden.<path>
sollte der Pfad der Seite sein, die Sie anzeigen möchten. Für/posts/foo
verwenden Sie&slug=/posts/foo
.
Ihr Headless CMS könnte es ermöglichen, eine Variable in der Entwurfs-URL zu verwenden, sodass <path>
dynamisch basierend auf den CMS-Daten gesetzt wird, z.B.: &slug=/posts/{entry.fields.slug}
Schließlich im Route Handler:
- Überprüfen Sie, ob das Secret übereinstimmt und der
slug
-Parameter existiert (falls nicht, sollte die Anfrage fehlschlagen). - Rufen Sie
draftMode.enable()
auf, um das Cookie zu setzen. - Leiten Sie den Browser dann zum angegebenen
slug
-Pfad weiter.
// Route Handler mit Secret und Slug
import { draftMode } from 'next/headers'
import { redirect } from 'next/navigation'
export async function GET(request: Request) {
// Query-String-Parameter parsen
const { searchParams } = new URL(request.url)
const secret = searchParams.get('secret')
const slug = searchParams.get('slug')
// Secret und Parameter überprüfen
// Dieses Secret sollte nur diesem Route Handler und dem CMS bekannt sein
if (secret !== 'MY_SECRET_TOKEN' || !slug) {
return new Response('Invalid token', { status: 401 })
}
// Headless CMS abfragen, um zu prüfen, ob der Slug existiert
// getPostBySlug implementiert die erforderliche Abfrage-Logik für das Headless CMS
const post = await getPostBySlug(slug)
// Wenn der Slug nicht existiert, wird der Draft Mode nicht aktiviert
if (!post) {
return new Response('Invalid slug', { status: 401 })
}
// Draft Mode durch Setzen des Cookies aktivieren
draftMode().enable()
// Zum Pfad des abgerufenen Posts weiterleiten
// Nicht zu searchParams.slug, um Open-Redirect-Schwachstellen zu vermeiden
redirect(post.slug)
}
// Route Handler mit Secret und Slug
import { draftMode } from 'next/headers'
import { redirect } from 'next/navigation'
export async function GET(request) {
// Query-String-Parameter parsen
const { searchParams } = new URL(request.url)
const secret = searchParams.get('secret')
const slug = searchParams.get('slug')
// Secret und Parameter überprüfen
// Dieses Secret sollte nur diesem Route Handler und dem CMS bekannt sein
if (secret !== 'MY_SECRET_TOKEN' || !slug) {
return new Response('Invalid token', { status: 401 })
}
// Headless CMS abfragen, um zu prüfen, ob der Slug existiert
// getPostBySlug implementiert die erforderliche Abfrage-Logik für das Headless CMS
const post = await getPostBySlug(slug)
// Wenn der Slug nicht existiert, wird der Draft Mode nicht aktiviert
if (!post) {
return new Response('Invalid slug', { status: 401 })
}
// Draft Mode durch Setzen des Cookies aktivieren
draftMode().enable()
// Zum Pfad des abgerufenen Posts weiterleiten
// Nicht zu searchParams.slug, um Open-Redirect-Schwachstellen zu vermeiden
redirect(post.slug)
}
Bei Erfolg wird der Browser mit dem Draft-Mode-Cookie zum gewünschten Pfad weitergeleitet.
Schritt 2: Seite aktualisieren
Der nächste Schritt besteht darin, Ihre Seite so zu aktualisieren, dass sie den Wert von draftMode().isEnabled
überprüft.
Wenn Sie eine Seite aufrufen, für die das Cookie gesetzt ist, werden die Daten zur Laufzeit (request time) statt zur Build-Zeit abgerufen.
Außerdem ist der Wert von isEnabled
dann true
.
// Seite, die Daten abruft
import { draftMode } from 'next/headers'
async function getData() {
const { isEnabled } = draftMode()
const url = isEnabled
? 'https://draft.example.com'
: 'https://production.example.com'
const res = await fetch(url)
return res.json()
}
export default async function Page() {
const { title, desc } = await getData()
return (
<main>
<h1>{title}</h1>
<p>{desc}</p>
</main>
)
}
// Seite, die Daten abruft
import { draftMode } from 'next/headers'
async function getData() {
const { isEnabled } = draftMode()
const url = isEnabled
? 'https://draft.example.com'
: 'https://production.example.com'
const res = await fetch(url)
return res.json()
}
export default async function Page() {
const { title, desc } = await getData()
return (
<main>
<h1>{title}</h1>
<p>{desc}</p>
</main>
)
}
Das war's! Wenn Sie den Draft-Route-Handler (mit secret
und slug
) von Ihrem Headless CMS oder manuell aufrufen, sollten Sie nun den Entwurfsinhalt sehen können. Und wenn Sie Ihren Entwurf ohne Veröffentlichung aktualisieren, sollten Sie den Entwurf einsehen können.
Setzen Sie dies als Entwurfs-URL in Ihrem Headless CMS oder rufen Sie sie manuell auf, und Sie sollten den Entwurf sehen können.
https://<your-site>/api/draft?secret=<token>&slug=<path>
Weitere Details
Draft-Mode-Cookie löschen
Standardmäßig endet die Draft-Mode-Sitzung, wenn der Browser geschlossen wird.
Um das Draft-Mode-Cookie manuell zu löschen, erstellen Sie einen Route Handler, der draftMode().disable()
aufruft:
import { draftMode } from 'next/headers'
export async function GET(request: Request) {
draftMode().disable()
return new Response('Draft mode is disabled')
}
import { draftMode } from 'next/headers'
export async function GET(request) {
draftMode().disable()
return new Response('Draft mode is disabled')
}
Rufen Sie dann /api/disable-draft
auf, um den Route Handler auszuführen. Wenn Sie diese Route mit next/link
aufrufen, müssen Sie prefetch={false}
übergeben, um ein versehentliches Löschen des Cookies beim Prefetch zu verhindern.
Einzigartig pro next build
Bei jedem Aufruf von next build
wird ein neuer Bypass-Cookie-Wert generiert.
Dies stellt sicher, dass der Bypass-Cookie nicht erraten werden kann.
Gut zu wissen: Um Draft Mode lokal über HTTP zu testen, muss Ihr Browser Third-Party-Cookies und Local Storage-Zugriff erlauben.