llahi.dev

Consejos para creación de sitios web rápidos y basados ​​en contenido.

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:

Terminal window
npx create-astro@latest my-isr-site --template with-tailwindcss --install --add react --git

Añ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:

Terminal window
npx astro add vercel

El 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 /api para no cachear ningún endpoint de nuestra API.

Así debería verse tu archivo astro.config.mjs:

astro.config.mjs
// @ts-check
import { defineConfig } from "astro/config";
import tailwindcss from "@tailwindcss/vite";
import vercel from "@astrojs/vercel";
// https://astro.build/config
export 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 bypassToken debe 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.

src/pages/index.astro
---
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:

  1. Creamos el archivo src/pages/api/invalidate.ts con un endpoint POST.
  2. Hacemos una petición fetch interna con el método HEAD y la cabecera del token.
  3. Comprobamos si la cabecera X-Vercel-Cache devuelve REVALIDATED.
src/pages/api/invalidate.ts
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:

Terminal window
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. 🎉🚀