Saltar al contenido

Qué es un adapter y por qué SSR lo necesita

La pieza que falta cuando un sitio deja de ser estático: el adapter como interfaz entre el motor de Astro y un runtime concreto. Por qué el modo estático no lo necesita y el bajo demanda sí, cómo el par Request/Response de la plataforma web es el contrato compartido, cómo se instala y registra con astro add, y cómo estático y dinámico conviven en un mismo build.

Sin servidor no hay quién ejecute tu código

Un sitio estático es un montón de ficheros terminados. El build los cuece una vez, y a partir de ahí servirlos es un acto mecánico: un CDN o un cubo de almacenamiento devuelve bytes que ya existían, sin computar nada. Por eso el modo static no pide adapter —no hay código tuyo corriendo en producción, solo artefactos horneados—.

El renderizado bajo demanda rompe esa foto. Una ruta con export const prerender = false no se resuelve en el build: se resuelve cuando llega la petición, leyendo Astro.params, consultando datos frescos, decidiendo la respuesta al vuelo. Eso exige un proceso vivo que ejecute tu código en cada visita. Astro sabe producir ese código —su build genera un manejador de peticiones—, pero no sabe, por sí mismo, cómo la plataforma de destino lo arranca ni con qué forma le entrega cada petición. Ese saber es justo lo que aporta el adapter.

El adapter: un traductor entre dos formas de petición

El motor de Astro está escrito contra la plataforma web. Su corazón es una aplicación que recibe un Request estándar y devuelve un Response estándar —los mismos objetos que existen en cualquier navegador—. Esa firma es universal y no menciona a ningún proveedor.

TypeScript
// La idea del contrato interno, no codigo que escribas a diarioconst app = new App(manifest);const response = await app.render(request); // Request -> Response

El problema es que ningún runtime real habla exactamente ese dialecto. Node entrega un IncomingMessage y espera que escribas en un ServerResponse. Una función serverless recibe un objeto de evento con su propia forma. Un Worker de Cloudflare ya trae una petición casi estándar, pero con extras propios. El adapter es el traductor bidireccional: toma la petición nativa de la plataforma, la convierte en el Request que el motor espera, y transforma el Response de vuelta en lo que el runtime sabe emitir.

Esa es la razón por la que nunca escribes manejo de peticiones específico de una plataforma dentro de tus páginas. No parseas cabeceras al estilo de Node ni construyes la salida con la API de un proveedor: lees Astro.request, devuelves un Response, y confías en que el adapter haga la conversión en ambos sentidos. Toda la especificidad del runtime empieza y termina en esa capa delgada.

Instalar y registrar un adapter

La forma canónica de añadir un adapter es astro add, que instala el paquete, lo registra en astro.config.mjs y ajusta lo que haga falta sin que edites nada a mano.

Shell
# Elige el destino: node, vercel, netlify o cloudflarenpx astro add node# instala @astrojs/node, importa el paquete y rellena la clave adapter

El resultado en la configuración es una sola línea nueva, pero es la que cambia todo el destino del proyecto:

JS
import { defineConfig } from 'astro/config';import node from '@astrojs/node';export default defineConfig({  adapter: node({ mode: 'standalone' }),});

Con el adapter presente, las rutas bajo demanda ya tienen dónde ejecutarse. Fíjate en lo que no ha cambiado: ni una sola de tus páginas. El acoplamiento a la plataforma cabe entero en esa importación y esa clave; el resto de tu código sigue hablando el lenguaje universal del motor. Astro mantiene un puñado de adapters oficiales, uno por familia de destino.

Estático y dinámico conviven en el mismo build

Con un adapter presente no estás obligado a volver dinámico todo el sitio. El output puede seguir siendo static y tú marcas bajo demanda solo las rutas que lo necesiten con export const prerender = false. El build entiende esa mezcla y produce dos artefactos complementarios.

Shell
dist/  client/   # HTML prerenderizado y assets, servibles por un CDN  server/   # el handler que ejecuta las rutas bajo demanda

La parte de client son ficheros terminados que la plataforma sirve sin computar nada; la de server es el código que el adapter conecta al runtime para las rutas vivas. El adapter no solo traduce peticiones: también organiza este reparto, indicándole a la plataforma qué servir como estático y qué enviar a tu manejador.

ASTRO
---// src/pages/blog/[slug].astro  ->  estatico por defecto// src/pages/carrito.astro      ->  bajo demandaexport const prerender = false;---

El mismo mecanismo funciona al revés. Si configuras output: 'server', todo se vuelve bajo demanda por defecto y marcas con export const prerender = true las páginas que sí quieras hornear —la portada, el aviso legal—. Estático y servidor no son dos proyectos distintos, sino dos posiciones por defecto del mismo dial, y el adapter sostiene cualquiera de ellas sin que cambie nada más en tu código.