Introducción/Guías/ISR

Cómo implementar Regeneración Estática Incremental (ISR)

Ejemplos

La Regeneración Estática Incremental (ISR) permite:

  • Actualizar contenido estático sin reconstruir todo el sitio
  • Reducir la carga del servidor sirviendo páginas estáticas prerrenderizadas para la mayoría de solicitudes
  • Asegurar que los encabezados cache-control adecuados se añadan automáticamente a las páginas
  • Manejar grandes cantidades de páginas de contenido sin tiempos largos de next build

Aquí un ejemplo mínimo:

interface Post {
  id: string
  title: string
  content: string
}

// Next.js invalidará la caché cuando llegue una
// solicitud, como máximo una vez cada 60 segundos.
export const revalidate = 60

// Prerrenderizaremos solo los parámetros de `generateStaticParams` en tiempo de compilación.
// Si llega una solicitud para una ruta no generada,
// Next.js renderizará la página en el servidor bajo demanda.
export const dynamicParams = true // o false, para mostrar 404 en rutas desconocidas

export async function generateStaticParams() {
  const posts: Post[] = await fetch('https://api.vercel.app/blog').then((res) =>
    res.json()
  )
  return posts.map((post) => ({
    id: String(post.id),
  }))
}

export default async function Page({
  params,
}: {
  params: Promise<{ id: string }>
}) {
  const { id } = await params
  const post: Post = await fetch(`https://api.vercel.app/blog/${id}`).then(
    (res) => res.json()
  )
  return (
    <main>
      <h1>{post.title}</h1>
      <p>{post.content}</p>
    </main>
  )
}

Así funciona este ejemplo:

  1. Durante next build, se generan todas las entradas de blog conocidas (hay 25 en este ejemplo)
  2. Todas las solicitudes a estas páginas (ej. /blog/1) se almacenan en caché y son instantáneas
  3. Después de 60 segundos, la siguiente solicitud mostrará la página en caché (obsoleta)
  4. La caché se invalida y comienza a generarse una nueva versión de la página en segundo plano
  5. Una vez generada con éxito, Next.js mostrará y almacenará en caché la página actualizada
  6. Si se solicita /blog/26, Next.js generará y almacenará esta página bajo demanda

Referencia

Configuración del segmento de ruta

Funciones

Ejemplos

Revalidación basada en tiempo

Esto obtiene y muestra una lista de entradas de blog en /blog. Después de una hora, la caché para esta página se invalida en la próxima visita. Luego, en segundo plano, se genera una nueva versión con las entradas más recientes.

interface Post {
  id: string
  title: string
  content: string
}

export const revalidate = 3600 // invalida cada hora

export default async function Page() {
  const data = await fetch('https://api.vercel.app/blog')
  const posts: Post[] = await data.json()
  return (
    <main>
      <h1>Entradas del Blog</h1>
      <ul>
        {posts.map((post) => (
          <li key={post.id}>{post.title}</li>
        ))}
      </ul>
    </main>
  )
}

Recomendamos establecer un tiempo alto de revalidación. Por ejemplo, 1 hora en lugar de 1 segundo. Si necesita más precisión, considere usar revalidación bajo demanda. Para datos en tiempo real, considere cambiar a renderizado dinámico.

Revalidación bajo demanda con revalidatePath

Para un método más preciso de revalidación, invalide páginas bajo demanda con la función revalidatePath.

Por ejemplo, esta Acción de Servidor se llamaría después de agregar una nueva entrada. Independientemente de cómo obtenga los datos en su Componente de Servidor, ya sea usando fetch o conectando a una base de datos, esto limpiará la caché para toda la ruta y permitirá al Componente de Servidor obtener datos frescos.

'use server'

import { revalidatePath } from 'next/cache'

export async function createPost() {
  // Invalida la ruta /posts en la caché
  revalidatePath('/posts')
}

Ver demo y explorar código fuente.

Revalidación bajo demanda con revalidateTag

Para la mayoría de casos, prefiera revalidar rutas completas. Si necesita control más granular, use revalidateTag. Por ejemplo, puede etiquetar llamadas fetch individuales:

export default async function Page() {
  const data = await fetch('https://api.vercel.app/blog', {
    next: { tags: ['posts'] },
  })
  const posts = await data.json()
  // ...
}

Si usa un ORM o conecta a una base de datos, puede usar unstable_cache:

import { unstable_cache } from 'next/cache'
import { db, posts } from '@/lib/db'

const getCachedPosts = unstable_cache(
  async () => {
    return await db.select().from(posts)
  },
  ['posts'],
  { revalidate: 3600, tags: ['posts'] }
)

export default async function Page() {
  const posts = getCachedPosts()
  // ...
}

Luego puede usar revalidateTag en Acciones de Servidor o Manejadores de Ruta:

'use server'

import { revalidateTag } from 'next/cache'

export async function createPost() {
  // Invalida todos los datos etiquetados con 'posts' en la caché
  revalidateTag('posts')
}

Manejo de excepciones no capturadas

Si ocurre un error al intentar revalidar datos, se seguirán sirviendo los últimos datos generados exitosamente desde la caché. En la siguiente solicitud, Next.js reintentará revalidar. Más sobre manejo de errores.

Personalizando la ubicación de la caché

Puede configurar la ubicación de la caché de Next.js si desea persistir páginas y datos en almacenamiento duradero, o compartir la caché entre múltiples contenedores o instancias de su aplicación. Más información.

Solución de problemas

Depuración de datos en caché en desarrollo local

Si usa la API fetch, puede añadir registro adicional para entender qué solicitudes están en caché o no. Más sobre la opción logging.

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

Verificar el comportamiento correcto en producción

Para verificar que sus páginas se almacenan en caché y se revalidan correctamente en producción, puede probar localmente ejecutando next build y luego next start para ejecutar el servidor de producción de Next.js.

Esto le permitirá probar el comportamiento de ISR (Regeneración Incremental Estática) como funcionaría en un entorno de producción. Para depuración adicional, agregue la siguiente variable de entorno a su archivo .env:

.env
NEXT_PRIVATE_DEBUG_CACHE=1

Esto hará que el servidor de Next.js registre en la consola los aciertos y fallos de la caché ISR. Puede inspeccionar la salida para ver qué páginas se generan durante next build, así como cómo se actualizan las páginas cuando se accede a las rutas bajo demanda.

Consideraciones

  • ISR solo es compatible cuando se utiliza el entorno de ejecución Node.js (predeterminado).
  • ISR no es compatible al crear una Exportación Estática.
  • Si tiene múltiples solicitudes fetch en una ruta renderizada estáticamente, y cada una tiene una frecuencia de revalidate diferente, se utilizará el tiempo más bajo para ISR. Sin embargo, esas frecuencias de revalidación seguirán siendo respetadas por la Caché de Datos.
  • Si alguna de las solicitudes fetch utilizadas en una ruta tiene un tiempo de revalidate de 0, o un no-store explícito, la ruta se renderizará dinámicamente.
  • El Middleware no se ejecutará para solicitudes ISR bajo demanda, lo que significa que cualquier reescritura de ruta o lógica en el Middleware no se aplicará. Asegúrese de revalidar la ruta exacta. Por ejemplo, /post/1 en lugar de una reescritura /post-1.

Compatibilidad con plataformas

Opción de despliegueCompatible
Servidor Node.js
Contenedor Docker
Exportación estáticaNo
AdaptadoresDepende de la plataforma

Aprenda cómo configurar ISR al alojar Next.js usted mismo.

Historial de versiones

VersiónCambios
v14.1.0El cacheHandler personalizado es estable.
v13.0.0Se introduce el App Router.
v12.2.0Pages Router: ISR bajo demanda es estable
v12.0.0Pages Router: Se añade ISR con detección de bots.
v9.5.0Pages Router: Se introduce ISR estable.