Saltar al contenido

Diseñar el render por página: el mapa de decisión

El dial de renderizado no es un interruptor del proyecto sino una decisión por ruta, y un producto real usa las cuatro posiciones a la vez. Dos preguntas —cuán fresco debe ser el dato y si se personaliza por usuario— deciden cada página, y el mapa se aplica a un producto completo: e-commerce con blog, dashboard y documentación, con la elección de edge o región como último matiz.

Dos preguntas deciden el render de cada ruta

Toda la complejidad del renderizado se colapsa en dos preguntas, y su cruce forma un cuadrante que no deja huecos.

La primera: ¿el dato de esta página cambia entre el build y la petición? Si basta con lo que había al construir —un artículo, una página legal, la documentación—, es estático: se hornea una vez y lo sirve un CDN sin ejecutar nada. Si el dato debe estar fresco en el instante de la visita —un stock, un precio, un panel—, es dinámico y necesita resolverse bajo demanda.

La segunda: ¿la página es igual para todos o se personaliza por usuario? Una portada idéntica para el mundo entero es cacheable aunque su dato sea algo dinámico; un carrito o un dashboard dependen de quién pregunta y no se pueden compartir entre visitantes. El cruce de ambos ejes te dice si la ruta es estática, una server island cacheable, o SSR por usuario.

ASTRO
---// El dial se acciona por pagina con una lineaexport const prerender = true;   // horneada en el build, servida por CDN// export const prerender = false; // bajo demanda, resuelta en cada peticion---

El cuadrante, sin huecos

Cruzar los dos ejes produce cuatro casillas, y toda página del mundo cae en una de ellas. Nombrarlas convierte la intuición en método.

El mapa aplicado a un producto real

Tomemos un producto completo —una tienda con blog, cuenta de usuario y documentación— y coloquemos cada zona en el dial. Este reparto es el patrón, no la excepción.

Fíjate en que el listado de productos es el caso más interesante: la rejilla, los filtros y el texto son estáticos y cacheables, pero el precio y la disponibilidad son server islands. Una página que parece dinámica es, en realidad, HTML estático servido al instante con unos pocos huecos que se rellenan con dato fresco. El patrón se lee limpio en el propio componente:

ASTRO
---// src/pages/tienda/[slug].astro  ->  estatico por defectoimport Precio from '../../components/Precio.astro';---<h1>{producto.nombre}</h1><p>{producto.descripcion}</p><Precio server:defer>  <span slot="fallback">Consultando precio...</span></Precio>

La búsqueda, en cambio, sí es dinámica de arriba abajo: es un endpoint o una página SSR porque su resultado depende por completo de lo que el usuario teclea, y no hay build que pueda anticiparlo.

TypeScript
// src/pages/api/buscar.ts  ->  dinamico de arriba abajo, nada que hornearexport const prerender = false;export async function GET({ url }) {  const q = url.searchParams.get('q') ?? '';  return Response.json(await buscarEnIndice(q));}

Esta asimetría es reveladora: dos rutas de la misma tienda —la ficha casi estática con un hueco fresco, la búsqueda entera dinámica— viven en extremos opuestos del dial porque su relación con el dato es opuesta. No hay un modo de render correcto para la tienda; hay uno correcto para cada una de sus páginas, y diseñar el render es desmenuzar el producto hasta que cada ruta cae, sola, en su casilla.

Edge o región: el último matiz

Cuando una ruta es SSR, queda una decisión más: dónde corre ese código. El edge —Workers repartidos por el globo— pone tu cómputo a milisegundos del usuario, ideal para personalización ligera, geolocalización y redirecciones rápidas. La región —una función serverless o un Node en un centro de datos— gana cuando el trabajo es pesado, necesita estar junto a la base de datos, o dura más de lo que un Worker tolera.

La server island añade el matiz más fino de todos: te deja mantener la página estática en el CDN y empujar al servidor solo el fragmento dinámico, con su propia cabecera de caché. Es el dial en su máxima granularidad —no la página o el servidor, sino este trozo aquí, con esta frescura—. Diseñar bien el render es, casi siempre, mantener el máximo de superficie en el extremo barato del dial y escalar quirúrgicamente lo mínimo imprescindible.

Ese fragmento se declara con server:defer sobre una página que sigue horneada: la cáscara es estática y solo el trozo marcado viaja al servidor, con su propio fallback mientras resuelve.

ASTRO
---// La pagina sigue estatica; solo el fragmento se resuelve en el servidorexport const prerender = true;---<article>{articulo.cuerpo}</article><Stock server:defer>  <span slot="fallback">Comprobando disponibilidad...</span></Stock>