Regeneración Estática Incremental
Next.js te permite crear o actualizar páginas estáticas después de haber construido tu sitio. La Regeneración Estática Incremental (ISR) te permite usar generación estática página por página, sin necesidad de reconstruir todo el sitio. Con ISR, puedes mantener los beneficios de lo estático mientras escalas a millones de páginas.
Importante: El runtime
edge
actualmente no es compatible con ISR, aunque puedes aprovecharstale-while-revalidate
configurando manualmente el encabezadocache-control
.
Para usar ISR, añade 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 ejecuta en el servidor durante el build.
// Puede llamarse nuevamente en una función serverless si
// la revalidación está activada 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 ejecuta en el servidor durante el build.
// 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 a pre-renderizar basadas en posts
const paths = posts.map((post) => ({
params: { id: post.id },
}))
// Pre-renderizaremos solo estas rutas durante el build.
// { 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 durante el build, inicialmente se mostrará la página en caché.
- Cualquier solicitud posterior a la página antes de que pasen 10 segundos también se sirve desde caché al instante.
- Pasada la ventana de 10 segundos, la siguiente solicitud seguirá mostrando la página en caché (obsoleta).
- Next.js activa una regeneración en segundo plano.
- Una vez que la página se regenera 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 solicita una ruta no 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 rollbacks.
Importante: Verifica si tu proveedor de datos tiene caché habilitada por defecto. Puedes necesitar desactivarla (ej.
useCdn: false
), de lo contrario una revalidación no podrá obtener datos frescos para actualizar la caché ISR. La caché puede ocurrir en un CDN (para un endpoint solicitado) cuando devuelve el encabezadoCache-Control
.
Revalidación Bajo Demanda
Si configuras un tiempo revalidate
de 60
, todos los visitantes verán la misma versión generada de tu sitio durante un minuto. La única forma de invalidar la caché es que alguien visite esa página después de que pase 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 actualizar tu sitio cuando:
- Se crea o actualiza contenido desde tu CMS headless
- Cambian metadatos de ecommerce (precio, descripción, categoría, reseñas, etc.)
Dentro de getStaticProps
, no necesitas especificar revalidate
para usar 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()
.
Importante: El Middleware no se ejecutará para solicitudes ISR bajo demanda. En su lugar, llama a
revalidate()
en la ruta exacta que deseas revalidar. Por ejemplo, si tienespages/blog/[slug].js
y un rewrite de/post-1
->/blog/post-1
, deberás llamar ares.revalidate('/blog/post-1')
.
Usando Revalidación Bajo Demanda
Primero, crea un token secreto conocido solo por tu app Next.js. Este secreto prevendrá acceso no autorizado a la ruta API de revalidación. Puedes acceder a la ruta (manualmente o con un webhook) con esta estructura de URL:
https://<your-site.com>/api/revalidate?secret=<token>
Luego, añade el secreto como una Variable de Entorno a tu aplicación. Finalmente, crea 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 ruta reescrita
// 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 exitosamente
return res.status(500).send('Error al revalidar')
}
}
Ver nuestra demo para ver la revalidación bajo demanda en acción y enviar feedback.
Probando ISR Bajo Demanda durante desarrollo
Al ejecutar localmente con next dev
, getStaticProps
se invoca en cada solicitud. Para verificar que tu configuración ISR bajo demanda es correcta, necesitarás crear un build de producción e iniciar el servidor de producción:
$ next build
$ next start
Luego, puedes confirmar que las páginas estáticas se han revalidado correctamente.
Manejo de errores y revalidación
Si hay un error dentro de getStaticProps
durante la regeneración en segundo plano, o lanzas un error manualmente, se seguirá mostrando la última página generada exitosamente. 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, puedes lanzar un error
// en lugar de devolver para que la caché no se actualice
// hasta la próxima solicitud exitosa.
throw new Error(`Error al obtener posts, estado recibido ${res.status}`)
}
// Si la solicitud fue exitosa, devuelve los posts
// y revalida 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 directamente al usar next start
.
Puedes usar este enfoque al desplegar en orquestadores de contenedores como Kubernetes o HashiCorp Nomad. Por defecto, los assets generados se almacenan en memoria en cada pod. Esto significa que cada pod tendrá su propia copia de los archivos estáticos. Puede mostrarse data obsoleta hasta que ese pod específico reciba una solicitud.
Para garantizar consistencia entre todos los pods, puedes desactivar el caché en memoria. Esto hará que el servidor Next.js solo use assets generados por ISR en el sistema de archivos.
Puedes usar un mount de red compartido en tus pods Kubernetes (o configuración similar) para reusar el mismo caché de sistema de archivos entre diferentes contenedores. Al compartir el mismo mount, la carpeta .next
que contiene el caché de next/image
también se compartirá y reusará.
Para desactivar el caché en memoria, configura isrMemoryCacheSize
a 0
en tu archivo next.config.js
:
module.exports = {
experimental: {
// Por defecto 50MB
isrMemoryCacheSize: 0, // tamaño del caché en bytes
},
}
Importante: Puedes necesitar considerar una condición de carrera entre múltiples pods intentando actualizar el caché al mismo tiempo, dependiendo de cómo esté configurado tu mount compartido.
Historial de Versiones
Versión | Cambios |
---|---|
v12.2.0 | ISR Bajo Demanda estable |
v12.1.0 | ISR Bajo Demanda añadido (beta). |
v12.0.0 | Fallback ISR consciente de bots añadido. |
v9.5.0 | Base Path añadido. |
getServerSideProps
Obtén datos en cada solicitud con `getServerSideProps`.
Obtención de datos del lado del cliente (Client-side Fetching)
Aprende sobre la obtención de datos del lado del cliente y cómo usar SWR, una biblioteca de hooks de React para fetching de datos que maneja caché, revalidación, seguimiento de foco, reobtención en intervalos y más.