Cómo configurar ISR bajo demanda para Astro en Vercel [draft]
Esta guía explica qué es la regeneración estática incremental (ISR) bajo demanda y cómo configurarla en Astro sobre Vercel para invalidar páginas en caché de forma específica.
En esta página:
¿Qué es ISR?
ISR (Incremental Static Regeneration) es un flujo que te permite actualizar contenido estático —como posts de un blog o endpoints de una API GET— sin tener que reconstruir o desplegar de nuevo todo tu sitio web para servir contenido estático actualizado desde tu caché, generalmente desde una CDN.
¿Qué es ISR bajo demanda?
Para el ISR normal, solemos establecer un TTL (Time To Live) de, por ejemplo, 1 hora o 1 día. Pasado ese tiempo, el contenido se invalida automáticamente y la siguiente solicitud activa una reconstrucción de la página y el almacenamiento en caché de la nueva versión. Con el ISR bajo demanda, obtienes un control adicional sobre tu caché, ya que puedes invalidarla en el momento que desees y forzar una nueva construcción incluso si aún no se ha alcanzado el tiempo del TTL.
¿Para qué casos de uso es bueno el ISR bajo demanda?
- Contenido que no cambia con frecuencia, pero que cuando lo hace, es crucial que los cambios se reflejen lo antes posible.
- Contenido al que se accede con frecuencia y cuya renderización es costosa, ya sea por potencia de cómputo, tiempo o por el coste de una API externa.
Nota: El TTL predeterminado de ISR en Vercel es ilimitado, hasta donde sé, pero se eliminaría en caso de que no se acceda al contenido durante 31 días.
Inicializar el proyecto Astro
En esta guía usaré la plantilla de Astro con Tailwind y React (aunque no necesitaremos ninguno de los dos) e inicializaré Git para subir el proyecto a GitHub y desplegarlo fácilmente en Vercel. Puedes hacer lo mismo con este comando:
npx create-astro@latest my-isr-site --template with-tailwindcss --install --add react --gitAñadir el adaptador de Vercel a Astro
Para configurar ISR, primero debemos añadir el adaptador de Vercel a nuestro proyecto ejecutando el siguiente comando y aceptando los cambios propuestos en nuestro archivo de configuración:
npx astro add vercelEl adaptador de Vercel se añadirá sin configuración personalizada. Vamos a añadir los siguientes ajustes de ISR:
- bypassToken: Una cadena de más de 32 caracteres que será nuestro secreto para autorizar las invalidaciones de caché (así solo nosotros podremos invalidarla bajo demanda).
- exclude: Excluiremos todas las rutas que comiencen con
/apipara no cachear ningún endpoint de nuestra API.
Así debería verse tu archivo astro.config.mjs:
// @ts-checkimport { defineConfig } from "astro/config";import tailwindcss from "@tailwindcss/vite";import vercel from "@astrojs/vercel";
// https://astro.build/configexport default defineConfig({ vite: { plugins: [tailwindcss()], }, /* * Configurando nuestro sitio para renderizado en servidor. * Vercel cacheará cada página por defecto debido a los ajustes ISR del adaptador. */ output: "server", adapter: vercel({ isr: { // Token secreto que usaremos más tarde para invalidar rutas bypassToken: "1234567890123456789012345678901234567890", // Excluimos nuestra API de ser cacheada exclude: [/^\/api\/.+/], }, }),});Nota: El
bypassTokendebe generarse en tiempo de construcción y nunca debe exponerse al cliente, ni siquiera a usuarios autenticados. Jamás debe salir del servidor.
Añadir una página dinámica
Vamos a añadir lo siguiente a nuestra página de inicio src/pages/index.astro. Solo renderizaremos la marca de tiempo en la que el servidor generó la página. Ten en cuenta que en desarrollo local la página no se cacheará, por lo que verás una nueva marca de tiempo en cada actualización.
---import "../styles/global.css";const renderedAt = new Date();---<html lang="es"> <head> ... </head> <body> <div class="grid place-items-center h-screen content-center"> <p>Renderizado en (Millis): {renderedAt.getTime()}</p> <p>Renderizado en (ISO): {renderedAt.toISOString()}</p> </div> </body></html>Si subimos los cambios a Vercel y vamos a nuestra URL, veremos la marca de tiempo. Si refrescamos, veremos que el valor se mantiene igual, lo que significa que estamos recibiendo la versión cacheada.
En la pestaña de red (Network), la cabecera x-vercel-cache debería mostrar el valor HIT.
Invalidación bajo demanda
Ahora solo queda invalidar la caché de la página de inicio mediante una solicitud API.
Para invalidar una ruta en Vercel, enviamos una solicitud GET o HEAD a esa ruta con la cabecera x-prerender-revalidate y el valor de nuestro bypassToken.
Para hacerlo sin exponer el token al cliente:
- Creamos el archivo
src/pages/api/invalidate.tscon un endpointPOST. - Hacemos una petición
fetchinterna con el métodoHEADy la cabecera del token. - Comprobamos si la cabecera
X-Vercel-CachedevuelveREVALIDATED.
import type { APIRoute } from "astro";
export const POST: APIRoute = async ({ url, request }) => { // Nota: Deberías proteger este endpoint con autenticación const body = await request.json(); const route = body.route ?? "/";
const res = await fetch(`https://${url.host}${route}`, { method: "HEAD", headers: { // NO escribas el token directamente en el código (hardcode) en producción "x-prerender-revalidate": "1234567890123456789012345678901234567890", }, });
const wasInvalidated = res.headers.get("X-Vercel-Cache") === "REVALIDATED"; return new Response(JSON.stringify({ wasInvalidated }));};Prueba final
Tras desplegar, si refrescamos la home el valor no cambiará. Pero si lanzamos este comando:
curl --location 'https://<tu-proyecto>.vercel.app/api/invalidate' \--header 'Content-Type: application/json' \--data '{ "route": "/" }'Recibiremos: {"wasInvalidated":true}. Al volver a la página de inicio, ¡la marca de tiempo se habrá actualizado!
¡Y eso es todo! Ya tienes configurado ISR bajo demanda para Astro en Vercel. 🎉🚀