Regeneración Estática Incremental (ISR)
Next.js le permite crear o actualizar páginas estáticas después de haber construido su sitio. La Regeneración Estática Incremental (ISR) le permite usar generación estática página por página, sin necesidad de reconstruir todo el sitio. Con ISR, puede mantener los beneficios de lo estático mientras escala a millones de páginas.
Nota importante: El entorno de ejecución
edge
actualmente no es compatible con ISR, aunque puede aprovecharstale-while-revalidate
configurando manualmente el encabezadocache-control
.
Para usar ISR, agregue la propiedad revalidate
a getStaticProps
:
function Blog({ posts }) {
return (
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
)
}
// Esta función se llama en el momento de construcción en el servidor.
// Puede llamarse nuevamente en una función serverless si
// la revalidación está habilitada y llega una nueva solicitud
export async function getStaticProps() {
const res = await fetch('https://.../posts')
const posts = await res.json()
return {
props: {
posts,
},
// Next.js intentará regenerar la página:
// - Cuando llegue una solicitud
// - Como máximo una vez cada 10 segundos
revalidate: 10, // En segundos
}
}
// Esta función se llama en el momento de construcción en el servidor.
// Puede llamarse nuevamente en una función serverless si
// la ruta no ha sido generada.
export async function getStaticPaths() {
const res = await fetch('https://.../posts')
const posts = await res.json()
// Obtener las rutas que queremos pre-renderizar basadas en los posts
const paths = posts.map((post) => ({
params: { id: post.id },
}))
// Pre-renderizaremos solo estas rutas en el momento de construcción.
// { fallback: 'blocking' } renderizará páginas en el servidor
// bajo demanda si la ruta no existe.
return { paths, fallback: 'blocking' }
}
export default Blog
Cuando se hace una solicitud a una página pre-renderizada en el momento de construcción, inicialmente se mostrará la página en caché.
- Cualquier solicitud a la página después de la inicial y antes de 10 segundos también se almacena en caché y es instantánea.
- Pasada la ventana de 10 segundos, la siguiente solicitud aún mostrará la página en caché (obsoleta).
- Next.js activa una regeneración de la página en segundo plano.
- Una vez que la página se genera con éxito, Next.js invalidará la caché y mostrará la página actualizada. Si la regeneración falla, la página antigua permanecerá sin cambios.
Cuando se hace una solicitud a una ruta que no ha sido generada, Next.js renderizará la página en el servidor en la primera solicitud. Las solicitudes futuras servirán el archivo estático desde la caché. ISR en Vercel persiste la caché globalmente y maneja reversiones.
Nota importante: Verifique si su proveedor de datos tiene caché habilitada por defecto. Puede que necesite deshabilitarla (ej.
useCdn: false
), de lo contrario una revalidación no podrá obtener datos frescos para actualizar la caché ISR. El almacenamiento en caché puede ocurrir en un CDN (para un endpoint solicitado) cuando devuelve el encabezadoCache-Control
.
Revalidación bajo demanda
Si configura un tiempo de revalidate
de 60
, todos los visitantes verán la misma versión generada de su sitio durante un minuto. La única forma de invalidar la caché es que alguien visite esa página después de que haya pasado el minuto.
A partir de v12.2.0
, Next.js soporta Regeneración Estática Incremental bajo demanda para purgar manualmente la caché de Next.js para una página específica. Esto facilita la actualización de su sitio cuando:
- Se crea o actualiza contenido desde su CMS headless
- Cambian metadatos de ecommerce (precio, descripción, categoría, reseñas, etc.)
Dentro de getStaticProps
, no necesita especificar revalidate
para usar la revalidación bajo demanda. Si revalidate
se omite, Next.js usará el valor por defecto false
(sin revalidación) y solo revalidará la página bajo demanda cuando se llame a revalidate()
.
Nota importante: El Middleware no se ejecutará para solicitudes ISR bajo demanda. En su lugar, llame a
revalidate()
en la ruta exacta que desea revalidar. Por ejemplo, si tienepages/blog/[slug].js
y una reescritura de/post-1
->/blog/post-1
, necesitará llamar ares.revalidate('/blog/post-1')
.
Usando revalidación bajo demanda
Primero, cree un token secreto conocido solo por su aplicación Next.js. Este secreto se usará para prevenir accesos no autorizados a la ruta API de revalidación. Puede acceder a la ruta (manualmente o con un webhook) con la siguiente estructura de URL:
https://<your-site.com>/api/revalidate?secret=<token>
Luego, agregue el secreto como una Variable de Entorno a su aplicación. Finalmente, cree la ruta API de revalidación:
export default async function handler(req, res) {
// Verificar el secreto para confirmar que es una solicitud válida
if (req.query.secret !== process.env.MY_SECRET_TOKEN) {
return res.status(401).json({ message: 'Token inválido' })
}
try {
// esto debe ser la ruta real, no una reescritura
// ej. para "/blog/[slug]" debe ser "/blog/post-1"
await res.revalidate('/path-to-revalidate')
return res.json({ revalidated: true })
} catch (err) {
// Si hay un error, Next.js continuará
// mostrando la última página generada con éxito
return res.status(500).send('Error al revalidar')
}
}
Vea nuestra demo para ver la revalidación bajo demanda en acción y enviar comentarios.
Probando ISR bajo demanda durante el desarrollo
Al ejecutar localmente con next dev
, getStaticProps
se invoca en cada solicitud. Para verificar que su configuración ISR bajo demanda es correcta, necesitará crear una compilación de producción e iniciar el servidor de producción:
$ next build
$ next start
Luego, puede confirmar que las páginas estáticas se han revalidado con éxito.
Manejo de errores y revalidación
Si hay un error dentro de getStaticProps
durante la regeneración en segundo plano, o si lanza un error manualmente, se seguirá mostrando la última página generada con éxito. En la siguiente solicitud, Next.js reintentará llamar a getStaticProps
.
export async function getStaticProps() {
// Si esta solicitud lanza un error no capturado, Next.js
// no invalidará la página actualmente mostrada y
// reintentará getStaticProps en la siguiente solicitud.
const res = await fetch('https://.../posts')
const posts = await res.json()
if (!res.ok) {
// Si hay un error del servidor, puede que quiera
// lanzar un error en lugar de devolver para que la caché no se actualice
// hasta la siguiente solicitud exitosa.
throw new Error(`Error al obtener posts, estado recibido ${res.status}`)
}
// Si la solicitud fue exitosa, devuelva los posts
// y revalide cada 10 segundos.
return {
props: {
posts,
},
revalidate: 10,
}
}
Auto-hospedaje de ISR
La Regeneración Estática Incremental (ISR) funciona en sitios Next.js auto-hospedados sin configuración adicional cuando usa next start
.
Puede usar este enfoque al implementar en orquestadores de contenedores como Kubernetes o HashiCorp Nomad. Por defecto, los recursos generados se almacenan en memoria en cada pod. Esto significa que cada pod tendrá su propia copia de los archivos estáticos. Pueden mostrarse datos obsoletos hasta que ese pod específico reciba una solicitud.
Para garantizar consistencia entre todos los pods, puede deshabilitar el almacenamiento en caché en memoria. Esto informará al servidor Next.js que solo use recursos generados por ISR en el sistema de archivos.
Puede usar un montaje de red compartido en sus pods de Kubernetes (o configuración similar) para reutilizar la misma caché de sistema de archivos entre diferentes contenedores. Al compartir el mismo montaje, la carpeta .next
que contiene la caché de next/image
también se compartirá y reutilizará.
Para deshabilitar el almacenamiento en caché en memoria, configure isrMemoryCacheSize
a 0
en su archivo next.config.js
:
module.exports = {
experimental: {
// Por defecto 50MB
isrMemoryCacheSize: 0, // tamaño de caché en bytes
},
}
Nota importante: Puede que necesite considerar una condición de carrera entre múltiples pods intentando actualizar la caché al mismo tiempo, dependiendo de cómo esté configurado su montaje compartido.
Historial de versiones
Versión | Cambios |
---|---|
v12.2.0 | ISR bajo demanda es estable |
v12.1.0 | ISR bajo demanda añadido (beta). |
v12.0.0 | Retroceso ISR consciente de bots añadido. |
v9.5.0 | Ruta base añadida. |