Comment prévisualiser du contenu avec le mode Prévisualisation dans Next.js

Remarque : Cette fonctionnalité est remplacée par le Mode Brouillon.

Exemples

Dans la documentation sur les Pages et la documentation sur la récupération de données, nous avons expliqué comment pré-rendre une page au moment de la construction (Génération Statique) en utilisant getStaticProps et getStaticPaths.

La Génération Statique est utile lorsque vos pages récupèrent des données depuis un CMS headless. Cependant, ce n'est pas idéal lorsque vous écrivez un brouillon sur votre CMS headless et que vous souhaitez le prévisualiser immédiatement sur votre page. Vous voudriez que Next.js rende ces pages au moment de la requête plutôt qu'au moment de la construction et qu'il récupère le contenu du brouillon plutôt que le contenu publié. Vous voudriez que Next.js contourne la Génération Statique uniquement pour ce cas spécifique.

Next.js dispose d'une fonctionnalité appelée Mode Prévisualisation qui résout ce problème. Voici les instructions pour l'utiliser.

Étape 1 : Créer et accéder à une route API de prévisualisation

Consultez d'abord la documentation sur les Routes API si vous n'êtes pas familier avec les Routes API de Next.js.

Tout d'abord, créez une route API de prévisualisation. Elle peut avoir n'importe quel nom - par exemple pages/api/preview.js (ou .ts si vous utilisez TypeScript).

Dans cette route API, vous devez appeler setPreviewData sur l'objet de réponse. L'argument pour setPreviewData doit être un objet, et celui-ci peut être utilisé par getStaticProps (nous y reviendrons plus tard). Pour l'instant, nous utiliserons {}.

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

res.setPreviewData définit certains cookies sur le navigateur qui activent le mode prévisualisation. Toutes les requêtes à Next.js contenant ces cookies seront considérées comme étant en mode prévisualisation, et le comportement pour les pages générées statiquement changera (nous y reviendrons plus tard).

Vous pouvez tester cela manuellement en créant une route API comme ci-dessous et en y accédant manuellement depuis votre navigateur :

pages/api/preview.js
// Exemple simple pour le tester manuellement depuis votre navigateur.
export default function handler(req, res) {
  res.setPreviewData({})
  res.end('Mode prévisualisation activé')
}

Si vous ouvrez les outils de développement de votre navigateur et visitez /api/preview, vous remarquerez que les cookies __prerender_bypass et __next_preview_data seront définis pour cette requête.

Accès sécurisé depuis votre CMS Headless

En pratique, vous voudriez appeler cette route API de manière sécurisée depuis votre CMS headless. Les étapes spécifiques varieront selon le CMS headless que vous utilisez, mais voici quelques étapes communes que vous pourriez suivre.

Ces étapes supposent que le CMS headless que vous utilisez prend en charge la configuration d'URLs de prévisualisation personnalisées. Si ce n'est pas le cas, vous pouvez toujours utiliser cette méthode pour sécuriser vos URLs de prévisualisation, mais vous devrez construire et accéder à l'URL de prévisualisation manuellement.

Premièrement, vous devriez créer une chaîne de token secrète en utilisant un générateur de token de votre choix. Ce secret ne sera connu que par votre application Next.js et votre CMS headless. Ce secret empêche les personnes qui n'ont pas accès à votre CMS d'accéder aux URLs de prévisualisation.

Deuxièmement, si votre CMS headless prend en charge la configuration d'URLs de prévisualisation personnalisées, spécifiez ce qui suit comme URL de prévisualisation. Cela suppose que votre route API de prévisualisation se trouve à pages/api/preview.js.

Terminal
https://<votre-site>/api/preview?secret=<token>&slug=<chemin>
  • <votre-site> doit être votre domaine de déploiement.
  • <token> doit être remplacé par le token secret que vous avez généré.
  • <chemin> doit être le chemin de la page que vous souhaitez prévisualiser. Si vous voulez prévisualiser /posts/foo, alors vous devriez utiliser &slug=/posts/foo.

Votre CMS headless pourrait vous permettre d'inclure une variable dans l'URL de prévisualisation afin que <chemin> puisse être défini dynamiquement en fonction des données du CMS, comme ceci : &slug=/posts/{entry.fields.slug}

Enfin, dans la route API de prévisualisation :

  • Vérifiez que le secret correspond et que le paramètre slug existe (sinon, la requête doit échouer).
  • Appelez res.setPreviewData.
  • Puis redirigez le navigateur vers le chemin spécifié par slug. (L'exemple suivant utilise une redirection 307).
export default async (req, res) => {
  // Vérifiez le secret et les paramètres suivants
  // Ce secret ne doit être connu que de cette route API et du CMS
  if (req.query.secret !== 'MON_TOKEN_SECRET' || !req.query.slug) {
    return res.status(401).json({ message: 'Token invalide' })
  }

  // Récupérez le CMS headless pour vérifier si le `slug` fourni existe
  // getPostBySlug implémenterait la logique de récupération nécessaire vers le CMS headless
  const post = await getPostBySlug(req.query.slug)

  // Si le slug n'existe pas, empêchez l'activation du mode prévisualisation
  if (!post) {
    return res.status(401).json({ message: 'Slug invalide' })
  }

  // Activez le mode prévisualisation en définissant les cookies
  res.setPreviewData({})

  // Redirigez vers le chemin du post récupéré
  // Nous ne redirigeons pas vers req.query.slug car cela pourrait conduire à des vulnérabilités de redirection ouverte
  res.redirect(post.slug)
}

Si cela réussit, le navigateur sera redirigé vers le chemin que vous souhaitez prévisualiser avec les cookies de mode prévisualisation définis.

Étape 2 : Mettre à jour getStaticProps

L'étape suivante consiste à mettre à jour getStaticProps pour prendre en charge le mode prévisualisation.

Si vous demandez une page qui a getStaticProps avec les cookies de mode prévisualisation définis (via res.setPreviewData), alors getStaticProps sera appelé au moment de la requête (au lieu du moment de la construction).

De plus, il sera appelé avec un objet context où :

  • context.preview sera true.
  • context.previewData sera le même que l'argument utilisé pour setPreviewData.
export async function getStaticProps(context) {
  // Si vous demandez cette page avec les cookies de mode prévisualisation définis :
  //
  // - context.preview sera true
  // - context.previewData sera le même que
  //   l'argument utilisé pour `setPreviewData`.
}

Nous avons utilisé res.setPreviewData({}) dans la route API de prévisualisation, donc context.previewData sera {}. Vous pouvez utiliser cela pour transmettre des informations de session depuis la route API de prévisualisation vers getStaticProps si nécessaire.

Si vous utilisez également getStaticPaths, alors context.params sera également disponible.

Récupérer les données de prévisualisation

Vous pouvez mettre à jour getStaticProps pour récupérer des données différentes en fonction de context.preview et/ou context.previewData.

Par exemple, votre CMS headless pourrait avoir un point de terminaison API différent pour les posts en brouillon. Si c'est le cas, vous pouvez utiliser context.preview pour modifier l'URL du point de terminaison API comme ci-dessous :

export async function getStaticProps(context) {
  // Si context.preview est true, ajoutez "/preview" au point de terminaison API
  // pour demander des données de brouillon au lieu des données publiées. Cela variera
  // selon le CMS headless que vous utilisez.
  const res = await fetch(`https://.../${context.preview ? 'preview' : ''}`)
  // ...
}

C'est tout ! Si vous accédez à la route API de prévisualisation (avec secret et slug) depuis votre CMS headless ou manuellement, vous devriez maintenant pouvoir voir le contenu de prévisualisation. Et si vous mettez à jour votre brouillon sans le publier, vous devriez pouvoir prévisualiser le brouillon.

Définissez cela comme URL de prévisualisation sur votre CMS headless ou accédez-y manuellement, et vous devriez pouvoir voir la prévisualisation.

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

Plus de détails

Bon à savoir : pendant le rendu, next/router expose un indicateur isPreview, consultez la documentation sur l'objet router pour plus d'informations.

Spécifier la durée du mode Prévisualisation

setPreviewData prend un second paramètre optionnel qui doit être un objet d'options. Il accepte les clés suivantes :

  • maxAge : Spécifie le nombre (en secondes) pour que la session de prévisualisation dure.
  • path : Spécifie le chemin sous lequel le cookie doit être appliqué. Par défaut à / activant le mode prévisualisation pour tous les chemins.
setPreviewData(data, {
  maxAge: 60 * 60, // Les cookies de mode prévisualisation expirent dans 1 heure
  path: '/about', // Les cookies de mode prévisualisation s'appliquent aux chemins avec /about
})

Effacer les cookies du mode Prévisualisation

Par défaut, aucune date d'expiration n'est définie pour les cookies du mode Prévisualisation, donc la session de prévisualisation se termine lorsque le navigateur est fermé.

Pour effacer manuellement les cookies du mode Prévisualisation, créez une route API qui appelle clearPreviewData() :

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

Puis, envoyez une requête à /api/clear-preview-mode-cookies pour invoquer la Route API. Si vous appelez cette route en utilisant next/link, vous devez passer prefetch={false} pour empêcher l'appel à clearPreviewData pendant le préchargement des liens.

Si un chemin a été spécifié dans l'appel à setPreviewData, vous devez passer le même chemin à clearPreviewData :

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

  res.clearPreviewData({ path })
}

Limites de taille de previewData

Vous pouvez passer un objet à setPreviewData et le rendre disponible dans getStaticProps. Cependant, comme les données seront stockées dans un cookie, il y a une limitation de taille. Actuellement, les données de prévisualisation sont limitées à 2KB.

Fonctionne avec getServerSideProps

Le mode prévisualisation fonctionne également avec getServerSideProps. Il sera également disponible sur l'objet context contenant preview et previewData.

Bon à savoir : Vous ne devriez pas définir l'en-tête Cache-Control lors de l'utilisation du mode Prévisualisation car il ne peut pas être contourné. Nous recommandons plutôt d'utiliser ISR.

Fonctionne avec les Routes API

Les Routes API auront accès à preview et previewData sous l'objet de requête. Par exemple :

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

Unique par next build

La valeur du cookie de contournement et la clé privée pour chiffrer les previewData changent lorsque next build est terminé. Cela garantit que le cookie de contournement ne peut pas être deviné.

Bon à savoir : Pour tester le mode Prévisualisation localement via HTTP, votre navigateur devra autoriser les cookies tiers et l'accès au stockage local.