Introduction/Guides/ISR

Comment implémenter la régénération statique incrémentielle (ISR)

Exemples

La régénération statique incrémentielle (ISR) vous permet de :

  • Mettre à jour du contenu statique sans reconstruire tout le site
  • Réduire la charge du serveur en servant des pages statiques pré-rendues pour la plupart des requêtes
  • Garantir que les en-têtes cache-control appropriés sont automatiquement ajoutés aux pages
  • Gérer un grand nombre de pages de contenu sans temps de construction next build longs

Voici un exemple minimal :

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) },
  }))

  // Nous pré-rendrons uniquement ces chemins au moment de la construction.
  // { fallback: 'blocking' } rendra les pages côté serveur
  // à la demande si le chemin n'existe pas.
  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 invalidera le cache lorsqu'une
    // requête arrive, au maximum une fois toutes les 60 secondes.
    revalidate: 60,
  }
}

export default function Page({ post }: Props) {
  return (
    <main>
      <h1>{post.title}</h1>
      <p>{post.content}</p>
    </main>
  )
}

Voici comment cet exemple fonctionne :

  1. Pendant next build, tous les articles de blog connus sont générés (il y en a 25 dans cet exemple)
  2. Toutes les requêtes vers ces pages (par exemple /blog/1) sont mises en cache et instantanées
  3. Après 60 secondes écoulées, la prochaine requête affichera toujours la page mise en cache (obsolète)
  4. Le cache est invalidé et une nouvelle version de la page commence à être générée en arrière-plan
  5. Une fois générée avec succès, Next.js affichera et mettra en cache la page mise à jour
  6. Si /blog/26 est demandé, Next.js générera et mettra en cache cette page à la demande

Référence

Fonctions

Exemples

Validation à la demande avec res.revalidate()

Pour une méthode plus précise de revalidation, utilisez res.revalidate pour générer une nouvelle page à la demande depuis un Routeur API.

Par exemple, cette Route API peut être appelée à /api/revalidate?secret=<token> pour revalider un article de blog donné. Créez un token secret connu uniquement par votre application Next.js. Ce secret sera utilisé pour empêcher un accès non autorisé à la Route API de revalidation.

import type { NextApiRequest, NextApiResponse } from 'next'

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  // Vérifier le secret pour confirmer que c'est une requête valide
  if (req.query.secret !== process.env.MY_SECRET_TOKEN) {
    return res.status(401).json({ message: 'Token invalide' })
  }

  try {
    // Ce devrait être le chemin réel et non un chemin réécrit
    // par exemple pour "/posts/[id]" ce devrait être "/posts/1"
    await res.revalidate('/posts/1')
    return res.json({ revalidated: true })
  } catch (err) {
    // S'il y a une erreur, Next.js continuera
    // à afficher la dernière page générée avec succès
    return res.status(500).send('Erreur lors de la revalidation')
  }
}

Si vous utilisez la revalidation à la demande, vous n'avez pas besoin de spécifier un temps revalidate dans getStaticProps. Next.js utilisera la valeur par défaut false (pas de revalidation) et ne revalidera la page qu'à la demande lorsque res.revalidate() est appelé.

Gestion des exceptions non capturées

S'il y a une erreur dans getStaticProps lors de la régénération en arrière-plan, ou si vous lancez une erreur manuellement, la dernière page générée avec succès continuera d'être affichée. Lors de la prochaine requête, Next.js réessayera d'appeler getStaticProps.

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 }
}) => {
  // Si cette requête lève une erreur non capturée, Next.js ne
  // invalidera pas la page actuellement affichée et
  // réessayera getStaticProps lors de la prochaine requête.
  const res = await fetch(`https://api.vercel.app/blog/${params.id}`)
  const post: Post = await res.json()

  if (!res.ok) {
    // S'il y a une erreur serveur, vous pourriez vouloir
    // lever une erreur au lieu de retourner pour que le cache ne soit pas mis à jour
    // jusqu'à la prochaine requête réussie.
    throw new Error(`Échec de la récupération des articles, statut reçu ${res.status}`)
  }

  return {
    props: { post },
    // Next.js invalidera le cache lorsqu'une
    // requête arrive, au maximum une fois toutes les 60 secondes.
    revalidate: 60,
  }
}

Personnalisation de l'emplacement du cache

Vous pouvez configurer l'emplacement du cache Next.js si vous souhaitez persister les pages et données mises en cache vers un stockage durable, ou partager le cache entre plusieurs conteneurs ou instances de votre application Next.js. En savoir plus.

Dépannage

Débogage des données mises en cache en développement local

Si vous utilisez l'API fetch, vous pouvez ajouter des logs supplémentaires pour comprendre quelles requêtes sont mises en cache ou non. En savoir plus sur l'option logging.

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

Vérification du comportement en production

Pour vérifier que vos pages sont correctement mises en cache et revalidées en production, vous pouvez tester localement en exécutant next build puis next start pour lancer le serveur Next.js en mode production.

Cela vous permettra de tester le comportement de l'ISR (Incremental Static Regeneration) tel qu'il fonctionnerait dans un environnement de production. Pour un débogage approfondi, ajoutez la variable d'environnement suivante à votre fichier .env :

.env
NEXT_PRIVATE_DEBUG_CACHE=1

Cela fera en sorte que le serveur Next.js enregistre dans la console les succès et les échecs du cache ISR. Vous pouvez inspecter la sortie pour voir quelles pages sont générées lors de next build, ainsi que comment les pages sont mises à jour lorsque les chemins sont accédés à la demande.

Mises en garde

  • L'ISR n'est pris en charge que lors de l'utilisation du runtime Node.js (par défaut).
  • L'ISR n'est pas pris en charge lors de la création d'une exportation statique.
  • Le middleware ne sera pas exécuté pour les requêtes ISR à la demande, ce qui signifie que toute réécriture de chemin ou logique dans le middleware ne sera pas appliquée. Assurez-vous de revalider le chemin exact. Par exemple, /post/1 au lieu d'un chemin réécrit /post-1.

Prise en charge par les plateformes

Option de déploiementPris en charge
Serveur Node.jsOui
Conteneur DockerOui
Exportation statiqueNon
AdaptateursDépend de la plateforme

Apprenez comment configurer l'ISR lors de l'hébergement autonome de Next.js.

Historique des versions

VersionModifications
v14.1.0Le cacheHandler personnalisé est stable.
v13.0.0L'App Router est introduit.
v12.2.0Pages Router : L'ISR à la demande est stable
v12.0.0Pages Router : ISR avec prise en compte des bots ajouté.
v9.5.0Pages Router : ISR stable introduit.