Vorschaumodus

Hinweis: Diese Funktion wurde durch den Entwurfsmodus (Draft Mode) ersetzt.

Beispiele

In der Pages-Dokumentation und der Data Fetching-Dokumentation haben wir besprochen, wie Sie eine Seite zur Build-Zeit (Static Generation) mit getStaticProps und getStaticPaths vorrendern können.

Statische Generierung ist nützlich, wenn Ihre Seiten Daten von einem Headless-CMS abrufen. Sie ist jedoch nicht ideal, wenn Sie einen Entwurf in Ihrem Headless-CMS schreiben und diesen Entwurf sofort auf Ihrer Seite vorschauen möchten. In diesem Fall möchten Sie, dass Next.js diese Seiten zur Anfragezeit statt zur Build-Zeit rendert und den Entwurfsinhalt statt des veröffentlichten Inhalts abruft. Sie möchten, dass Next.js die statische Generierung nur für diesen speziellen Fall umgeht.

Next.js bietet eine Funktion namens Vorschaumodus (Preview Mode), die dieses Problem löst. Hier finden Sie Anleitungen zur Verwendung.

Schritt 1: Erstellen und Zugreifen auf eine Preview-API-Route

Werfen Sie zunächst einen Blick in die API Routes-Dokumentation, wenn Sie mit Next.js-API-Routen nicht vertraut sind.

Erstellen Sie zunächst eine Preview-API-Route. Sie kann beliebig benannt werden - z.B. pages/api/preview.js (oder .ts bei Verwendung von TypeScript).

In dieser API-Route müssen Sie setPreviewData auf dem Response-Objekt aufrufen. Das Argument für setPreviewData sollte ein Objekt sein und kann von getStaticProps verwendet werden (mehr dazu später). Für jetzt verwenden wir {}.

export default function handler(req, res) {
  // ...
  res.setPreviewData({})
  // ...
}

res.setPreviewData setzt einige Cookies im Browser, die den Vorschaumodus aktivieren. Jede Anfrage an Next.js, die diese Cookies enthält, wird als Vorschaumodus betrachtet, und das Verhalten für statisch generierte Seiten ändert sich (mehr dazu später).

Sie können dies manuell testen, indem Sie eine API-Route wie unten erstellen und sie manuell über Ihren Browser aufrufen:

pages/api/preview.js
// Einfaches Beispiel zum manuellen Testen im Browser.
export default function handler(req, res) {
  res.setPreviewData({})
  res.end('Vorschaumodus aktiviert')
}

Wenn Sie die Entwicklertools Ihres Browsers öffnen und /api/preview aufrufen, werden Sie feststellen, dass die Cookies __prerender_bypass und __next_preview_data für diese Anfrage gesetzt werden.

Sicherer Zugriff von Ihrem Headless-CMS

In der Praxis möchten Sie diese API-Route sicher von Ihrem Headless-CMS aus aufrufen. Die genauen Schritte hängen davon ab, welches Headless-CMS Sie verwenden, aber hier sind einige allgemeine Schritte, die Sie unternehmen könnten.

Diese Schritte setzen voraus, dass Ihr Headless-CMS das Setzen von benutzerdefinierten Vorschau-URLs unterstützt. Falls nicht, können Sie diese Methode dennoch verwenden, um Ihre Vorschau-URLs zu sichern, müssen die Vorschau-URL jedoch manuell erstellen und aufrufen.

Erstens sollten Sie einen geheimen Token-String mit einem Token-Generator Ihrer Wahl erstellen. Dieses Geheimnis sollte nur Ihrer Next.js-App und Ihrem Headless-CMS bekannt sein. Dies verhindert, dass Personen, die keinen Zugriff auf Ihr CMS haben, auf Vorschau-URLs zugreifen können.

Zweitens, wenn Ihr Headless-CMS das Setzen benutzerdefinierter Vorschau-URLs unterstützt, geben Sie Folgendes als Vorschau-URL an. Dies setzt voraus, dass sich Ihre Preview-API-Route unter pages/api/preview.js befindet.

Terminal
https://<your-site>/api/preview?secret=<token>&slug=<path>
  • <your-site> sollte Ihre Bereitstellungsdomäne sein.
  • <token> sollte durch den generierten geheimen Token ersetzt werden.
  • <path> sollte der Pfad der Seite sein, die Sie in der Vorschau anzeigen möchten. Wenn Sie /posts/foo in der Vorschau anzeigen möchten, sollten Sie &slug=/posts/foo verwenden.

Ihr Headless-CMS könnte es ermöglichen, eine Variable in der Vorschau-URL zu verwenden, sodass <path> dynamisch basierend auf den CMS-Daten gesetzt werden kann, z.B.: &slug=/posts/{entry.fields.slug}

Schließlich in der Preview-API-Route:

  • Überprüfen Sie, ob das Geheimnis übereinstimmt und ob der slug-Parameter vorhanden ist (falls nicht, sollte die Anfrage fehlschlagen).
  • Rufen Sie res.setPreviewData auf.
  • Leiten Sie dann den Browser zu dem durch slug angegebenen Pfad weiter. (Das folgende Beispiel verwendet eine 307-Weiterleitung).
export default async (req, res) => {
  // Überprüfen Sie das Geheimnis und die nächsten Parameter
  // Dieses Geheimnis sollte nur dieser API-Route und dem CMS bekannt sein
  if (req.query.secret !== 'MY_SECRET_TOKEN' || !req.query.slug) {
    return res.status(401).json({ message: 'Ungültiger Token' })
  }

  // Rufen Sie das Headless-CMS ab, um zu überprüfen, ob der angegebene `slug` existiert
  // getPostBySlug würde die erforderliche Abruflogik für das Headless-CMS implementieren
  const post = await getPostBySlug(req.query.slug)

  // Wenn der slug nicht existiert, verhindern Sie die Aktivierung des Vorschaumodus
  if (!post) {
    return res.status(401).json({ message: 'Ungültiger slug' })
  }

  // Aktivieren Sie den Vorschaumodus durch Setzen der Cookies
  res.setPreviewData({})

  // Weiterleitung zum Pfad des abgerufenen Beitrags
  // Wir leiten nicht zu req.query.slug weiter, da dies zu Open-Redirect-Schwachstellen führen könnte
  res.redirect(post.slug)
}

Wenn dies erfolgreich ist, wird der Browser zu dem gewünschten Vorschau-Pfad weitergeleitet, wobei die Vorschaumodus-Cookies gesetzt werden.

Schritt 2: Aktualisieren Sie getStaticProps

Der nächste Schritt besteht darin, getStaticProps für den Vorschaumodus anzupassen.

Wenn Sie eine Seite anfordern, die getStaticProps enthält, während die Vorschaumodus-Cookies gesetzt sind (über res.setPreviewData), wird getStaticProps zur Anfragezeit (statt zur Build-Zeit) aufgerufen.

Darüber hinaus wird es mit einem context-Objekt aufgerufen, bei dem:

  • context.preview true sein wird.
  • context.previewData identisch mit dem für setPreviewData verwendeten Argument sein wird.
export async function getStaticProps(context) {
  // Wenn Sie diese Seite mit gesetzten Vorschaumodus-Cookies anfordern:
  //
  // - context.preview wird true sein
  // - context.previewData wird identisch mit
  //   dem für `setPreviewData` verwendeten Argument sein.
}

Wir haben res.setPreviewData({}) in der Preview-API-Route verwendet, daher wird context.previewData {} sein. Sie können dies verwenden, um bei Bedarf Sitzungsinformationen von der Preview-API-Route an getStaticProps zu übergeben.

Wenn Sie auch getStaticPaths verwenden, steht context.params ebenfalls zur Verfügung.

Vorschaudaten abrufen

Sie können getStaticProps aktualisieren, um basierend auf context.preview und/oder context.previewData unterschiedliche Daten abzurufen.

Ihr Headless-CMS könnte beispielsweise einen anderen API-Endpunkt für Entwurfsbeiträge haben. In diesem Fall können Sie context.preview verwenden, um die API-Endpunkt-URL wie folgt zu modifizieren:

export async function getStaticProps(context) {
  // Wenn context.preview true ist, hängen Sie "/preview" an den API-Endpunkt an
  // um Entwurfsdaten statt veröffentlichter Daten anzufordern. Dies variiert
  // je nach verwendetem Headless-CMS.
  const res = await fetch(`https://.../${context.preview ? 'preview' : ''}`)
  // ...
}

Das war's! Wenn Sie die Preview-API-Route (mit secret und slug) von Ihrem Headless-CMS oder manuell aufrufen, sollten Sie nun den Vorschauinhalt sehen können. Und wenn Sie Ihren Entwurf aktualisieren, ohne ihn zu veröffentlichen, sollten Sie den Entwurf in der Vorschau sehen können.

Setzen Sie dies als Vorschau-URL in Ihrem Headless-CMS oder rufen Sie sie manuell auf, und Sie sollten die Vorschau sehen können.

Terminal
https://<your-site>/api/preview?secret=<token>&slug=<path>

Weitere Details

Gut zu wissen: Während des Renderings stellt next/router ein isPreview-Flag bereit, siehe die Router-Objekt-Dokumentation für weitere Informationen.

Dauer des Vorschaumodus festlegen

setPreviewData akzeptiert einen optionalen zweiten Parameter, der ein Optionsobjekt sein sollte. Es akzeptiert die folgenden Schlüssel:

  • maxAge: Gibt die Anzahl (in Sekunden) an, wie lange die Vorschausitzung dauern soll.
  • path: Gibt den Pfad an, unter dem der Cookie gelten soll. Standardmäßig /, wodurch der Vorschaumodus für alle Pfade aktiviert wird.
setPreviewData(data, {
  maxAge: 60 * 60, // Die Vorschaumodus-Cookies laufen nach 1 Stunde ab
  path: '/about', // Die Vorschaumodus-Cookies gelten für Pfade mit /about
})

Vorschaumodus-Cookies löschen

Standardmäßig ist für Vorschaumodus-Cookies kein Ablaufdatum festgelegt, sodass die Vorschausitzung endet, wenn der Browser geschlossen wird.

Um die Vorschaumodus-Cookies manuell zu löschen, erstellen Sie eine API-Route, die clearPreviewData() aufruft:

pages/api/clear-preview-mode-cookies.js
export default function handler(req, res) {
  res.clearPreviewData({})
}

Senden Sie dann eine Anfrage an /api/clear-preview-mode-cookies, um die API-Route aufzurufen. Wenn Sie diese Route mit next/link aufrufen, müssen Sie prefetch={false} übergeben, um zu verhindern, dass clearPreviewData während des Link-Prefetchings aufgerufen wird.

Wenn in der setPreviewData-Aufruf ein Pfad angegeben wurde, müssen Sie denselben Pfad an clearPreviewData übergeben:

pages/api/clear-preview-mode-cookies.js
export default function handler(req, res) {
  const { path } = req.query

  res.clearPreviewData({ path })
}

Größenbeschränkungen für previewData

Sie können ein Objekt an setPreviewData übergeben und es in getStaticProps verfügbar machen. Da die Daten jedoch in einem Cookie gespeichert werden, gibt es eine Größenbeschränkung. Derzeit sind Vorschaudaten auf 2KB beschränkt.

Funktioniert mit getServerSideProps

Der Vorschaumodus funktioniert auch mit getServerSideProps. Er wird ebenfalls im context-Objekt mit preview und previewData verfügbar sein.

Gut zu wissen: Sie sollten den Cache-Control-Header nicht setzen, wenn Sie den Vorschaumodus verwenden, da er nicht umgangen werden kann. Stattdessen empfehlen wir die Verwendung von ISR (Incremental Static Regeneration).

Funktioniert mit API-Routen

API-Routen haben Zugriff auf preview und previewData unter dem Request-Objekt. Zum Beispiel:

export default function myApiRoute(req, res) {
  const isPreview = req.preview
  const previewData = req.previewData
  // ...
}

Einzigartig pro next build

Sowohl der Bypass-Cookie-Wert als auch der private Schlüssel zur Verschlüsselung der previewData ändern sich, wenn next build abgeschlossen ist. Dadurch wird sichergestellt, dass der Bypass-Cookie nicht erraten werden kann.

Gut zu wissen: Um den Vorschaumodus lokal über HTTP zu testen, muss Ihr Browser Cookies von Drittanbietern und Zugriff auf den lokalen Speicher zulassen.