Estrategias: static-first, SSR selectivo y server islands
Con el eje entendido y su coste medido, queda decidir dónde poner cada página real. Tres estrategias ordenan la decisión —static-first como disciplina, SSR selectivo para lo que lo exige y server islands para lo casi estático con un punto vivo— gobernadas por un criterio: el tipo de página. Cómo elegir y por qué la granularidad de la decisión no deja de encogerse.
Entendido el eje y medido su precio, queda lo práctico: decidir, para cada página real, dónde ponerla. Tres estrategias ordenan esa decisión y se despliegan en granularidades cada vez más finas. Static-first es la disciplina de partida, que trata lo estático como norma y lo dinámico como excepción justificada. El SSR selectivo lleva bajo demanda las rutas enteras que de verdad lo exigen. Y las server islands descienden un peldaño más: incrustan un hueco dinámico dentro de una página por lo demás estática, disolviendo la elección de todo-o-nada a escala de componente. El criterio que las gobierna a las tres es siempre el mismo —el tipo de página— y este nivel se cierra aprendiendo a leerlo.
- Adoptar static-first como valor por defecto disciplinado del proyecto.
- Aplicar SSR selectivo solo a las rutas que lo justifican.
- Usar server islands para incrustar lo dinámico dentro de lo estático.
- Elegir la estrategia por el tipo de página, no por costumbre.
Static-first: lo barato como punto de partida
La primera estrategia no es una técnica sino una postura por defecto: todo es estático hasta que se demuestre que no puede serlo. Se mantiene output: 'static', se hornea cuanto se pueda, y cada ruta que aspire a bajo demanda debe justificar su gasto. La razón es la que este nivel viene repitiendo: lo estático es casi gratis de operar, se sirve instantáneo desde el edge, resiste una avalancha de tráfico sin despeinarse y no tiene servidor que pueda caerse.
Hay un segundo argumento, menos citado y muy poderoso: la superficie de ataque. Un fichero HTML servido desde una CDN no tiene lógica que explotar, ni conexión a base de datos que inyectar, ni proceso que tumbar. Cada página que dejas estática es una página que sale, además de rápida y barata, más segura y más resistente por construcción. Lo dinámico es una capacidad valiosa, pero también una responsabilidad: un servidor que mantener, parchear y vigilar.
Puesto en positivo, cada ruta que consigues hornear te regala de golpe cuatro propiedades que lo dinámico tendría que ganarse una a una:
- Velocidad: se sirve desde el nodo del edge más cercano, sin cómputo ni espera a ninguna fuente.
- Escala: el mismo fichero atiende un pico de tráfico enorme sin despertar servidor alguno.
- Resistencia: no hay proceso que se caiga; mientras la CDN viva, la página responde.
- Seguridad: sin lógica en vivo, no hay casi nada que un atacante pueda ejecutar.
Static-first no es dogmatismo anti-dinámico; es orden de prioridad. Empiezas por la respuesta barata y solo pagas por la cara cuando la naturaleza de la página lo impone —cuando lee la petición, cuando personaliza, cuando exige frescura al segundo—. Invertir ese orden, arrancar en output: 'server' y congelar lo que se pueda, es legítimo para una aplicación que es dinámica de raíz, pero para la mayoría de los sitios —contenido en su esencia— static-first minimiza las excepciones y, con ellas, el coste y la superficie de fallo.
SSR selectivo y server islands
Cuando una ruta entera depende de la petición, la marcas bajo demanda y ya está: eso es el SSR selectivo. Un buscador que lee la consulta, un panel de cuenta que valida una sesión, un carrito que refleja un estado vivo. Son páginas cuya sustancia es la petición, y para ellas el bajo demanda no es un lujo sino la única forma correcta.
---
// src/pages/cuenta.astro -> toda la pagina depende de la sesion
export const prerender = false;
const sesion = Astro.cookies.get('sesion')?.value;
const usuario = sesion ? await validarSesion(sesion) : null;
if (!usuario) return Astro.redirect('/entrar');
---
<h1>Hola, {usuario.nombre}</h1>
La clave del SSR selectivo es que sea selectivo: no arrastres al modo servidor páginas vecinas que no lo necesitan solo porque comparten diseño. Cada ruta lleva su propia bandera, y la de al lado —la portada, el aviso legal— puede seguir horneada aunque esta viva bajo demanda. Marcar de más es el desperdicio más común, y el que las server islands vienen a evitar.
Pero hay un caso intermedio muy común que ninguna de las dos posturas anteriores resuelve bien: una página casi toda estática con un solo trozo dinámico. Un artículo de blog cacheable con un saludo personalizado en la esquina; una ficha de producto horneada con un stock en vivo. Marcar la página entera como bajo demanda por ese trozo sería tirar a la basura la cacheabilidad de todo lo demás. Para eso están las server islands: marcas solo ese componente con la directiva server:defer, y Astro sirve la página como HTML estático cacheable con un hueco donde la isla se renderiza aparte, en el servidor, y se inyecta al llegar.
---
// La pagina se hornea y se cachea entera...
import Articulo from '../components/Articulo.astro';
import SaludoUsuario from '../components/SaludoUsuario.astro';
---
<Articulo />
<!-- ...salvo esta isla, que se renderiza bajo demanda y se inyecta -->
<SaludoUsuario server:defer>
<span slot="fallback">Hola</span>
</SaludoUsuario>
La isla en sí es un componente corriente que lee lo que necesita de la petición; lo único especial es la directiva que le pusiste al usarlo.
---
// src/components/SaludoUsuario.astro -> se renderiza en el servidor, por peticion
const usuario = await usuarioDeLaSesion(Astro.cookies);
---
<span>Hola, {usuario?.nombre ?? 'invitado'}</span>
Bajo el capó, la server island es un mecanismo simple y elegante. Astro hornea la página con un marcador en el lugar de la isla y un contenido de reserva visible —el slot de fallback—; el navegador recibe ese HTML estático al instante y, por detrás, pide solo el trozo diferido a una ruta especial que lo renderiza en el servidor y lo devuelve para ocupar el hueco. El resultado invierte la relación entre lo estático y lo dinámico: antes, un solo trozo vivo obligaba a servir viva la página entera; ahora la carcasa sigue siendo estática y cacheable, y es únicamente el fragmento el que se difiere. Cada parte se cachea según su propia naturaleza —la carcasa para siempre, la isla nunca o poco—, algo imposible cuando la unidad de decisión era la página completa.
Elegir por tipo de página
Las tres estrategias convergen en una sola pregunta operativa que se resuelve mirando qué clase de página tienes delante. La mayoría cae con nitidez en uno de tres cajones.
- Estática pura: landings, artículos, documentación, páginas institucionales. Contenido igual para todos y estable. Se hornean y punto.
- Bajo demanda entera: buscadores, paneles, carritos, checkout. Su sustancia es la petición o la sesión; el SSR selectivo es su sitio.
- Estática con isla: una página mayormente cacheable con un fragmento personalizado o en vivo. Estática de base con una server island para el trozo dinámico.
Una tienda ilustra los tres a la vez y enseña a repartir. La portada y las páginas de categoría son contenido estable: estáticas. La ficha de un producto es casi toda estática —descripción, fotos, especificaciones— con un dato vivo, el stock: candidata perfecta a server island, carcasa horneada más una isla para las existencias. Y el carrito o el checkout dependen enteramente de la sesión del comprador: bajo demanda sin discusión. Un mismo sitio, las tres estrategias, cada página en el cajón que le dicta su naturaleza y no una etiqueta global impuesta sobre todas.
Ante una página nueva, hazte tres preguntas en orden. ¿Es igual para todos y estable? Entonces estática. Si no, ¿es toda ella dependiente de la petición? Entonces bajo demanda entera. Si no —si solo un trozo lo es— entonces estática con una server island para ese trozo. Ese árbol de tres ramas resuelve la inmensa mayoría de los casos sin que tengas que teorizar sobre modos: partes del tipo de contenido y la estrategia se deduce sola.
El error de reparto más caro es marcar prerender = false en una página casi estática porque un rincón suyo necesita datos frescos. Con ese gesto sacrificas la cacheabilidad de todo —la descripción, las fotos, el texto que nunca cambia— para servir un solo dato vivo, y conviertes una página que iba a volar desde el edge en una que paga cómputo en cada visita. Casi siempre, la respuesta correcta no es volver dinámica la página sino aislar el trozo vivo en una server island y dejar que el resto siga horneado. Antes de accionar el interruptor a nivel de página, pregúntate si lo que necesita frescura es la página o solo un fragmento de ella.
Static-first
Todo estatico por defecto; cada ruta dinamica se justifica. La postura barata, segura y resistente.
SSR selectivo
Rutas enteras bajo demanda cuando su sustancia es la peticion: buscador, panel, carrito.
Server islands
Un hueco dinamico dentro de una pagina estatica y cacheable, con contenido de reserva.
Por tipo de pagina
Igual para todos, toda dependiente, o casi estatica con un trozo vivo: cada tipo, su estrategia.
flowchart TD
P[una pagina nueva] --> Q1{igual para todos y estable}
Q1 -->|si| EST[estatica pura]
Q1 -->|no| Q2{toda depende de la peticion}
Q2 -->|si| SSR[bajo demanda entera SSR selectivo]
Q2 -->|solo un trozo| ISL[estatica con server island]
style P fill:#89b4fa,color:#11111b
style EST fill:#a6e3a1,color:#11111b
style ISL fill:#f9e2af,color:#11111b
style SSR fill:#fab387,color:#11111bConviene no confundir las server islands con las islas de cliente que viste en la interactividad. Una isla de cliente hidrata JavaScript en el navegador para que un componente reaccione al usuario; una server island difiere el renderizado en el servidor de un fragmento y lo inyecta ya resuelto como HTML, sin mandar lógica al cliente. Una resuelve la interacción; la otra, la personalización o la frescura de un trozo dentro de una página por lo demás cacheable. Y como toda ruta con render bajo demanda, las server islands necesitan un adaptador instalado para ejecutarse.
Es tentador ver las server islands como una optimización marginal, pero son la resolución de la tensión central de todo este nivel. Durante años, la elección estático-o-dinámico fue de grano grueso: primero por sitio entero, luego —gran avance— por página. Las server islands la llevan al grano del componente, y con ello disuelven el falso dilema de la página mixta, que hasta ahora obligaba a sacrificar la cacheabilidad del todo por la dinamicidad de una parte. Ya no eliges por la página: eliges por cada pieza que la compone.
Visto así, las tres estrategias no compiten: se encajan. Static-first fija el suelo —todo horneado salvo prueba en contra—; el SSR selectivo levanta las pocas rutas que son aplicación entera; y las server islands recortan huecos vivos en las páginas que son casi documento. Un sitio bien pensado usa las tres a la vez, cada una en su escala, y el resultado es un reparto donde ninguna pieza paga más coste del que su naturaleza exige. No hay que elegir una estrategia para el proyecto: hay que aplicar la que corresponde a cada página, y a veces a cada fragmento.
Con esto cierras el nivel. Sabes qué es el eje de render, cómo fijarlo por página con prerender, qué te ofrece el objeto Astro bajo demanda, cómo se paga cada momento y con qué estrategia repartir tus páginas. Lo que queda por delante —imágenes, i18n, seguridad, despliegue— se construye sobre estas decisiones, porque el momento de render es el cimiento sobre el que se apoya todo lo demás de un sitio en producción.
Si miras la historia del renderizado web como una sola trayectoria, verás que cuenta una única historia: la unidad sobre la que se decide “estático o dinámico” no ha parado de encogerse, y cada contracción ha sido un avance. Al principio la decisión era por sitio: elegías, de una vez y para todo, entre un generador estático o un servidor de aplicaciones, y esa elección teñía cada rincón del proyecto aunque casi ninguna página encajara del todo en ella. Luego la decisión bajó a la página: prerender por ruta te dejó hornear el blog y servir vivo el buscador dentro del mismo proyecto, y el híbrido dejó de ser un tercer modo para volverse la norma. Las server islands dan el siguiente paso y bajan la decisión al componente: dentro de una misma página, el artículo se cachea para siempre y el saludo se difiere a la petición, cada uno con el momento de render que su naturaleza pide. El patrón es inconfundible, y su dirección también: hacia decisiones cada vez más locales, tomadas cada vez más cerca del trozo concreto de interfaz que las necesita. Lo que esto revela es que “estático” y “dinámico” nunca fueron propiedades de un sitio ni de una página, sino de cada dato y cada fragmento que la componen —el precio que cambia una vez al mes es estático por naturaleza aunque viva en una página con un stock que cambia cada minuto—. Durante décadas la tecnología nos obligó a promediar esas naturalezas dispares en una sola etiqueta para toda la unidad, y ese promedio siempre traicionaba a algo: horneabas lo que debía vivir, o servías vivo lo que podía congelarse. La trayectoria entera del campo es el esfuerzo por dejar de promediar, por permitir que cada pieza declare su propio momento. Astro 7 te sitúa muy cerca del final de ese camino: puedes elegir el momento de render por proyecto, por página y por componente, y elegirlo bien no es aplicar una receta sino leer la verdadera naturaleza de cada fragmento —cuánta frescura exige, para quién es, cada cuánto cambia— y darle exactamente el momento que le corresponde. El maestro del renderizado no memoriza modos: ve, en cada trozo de una interfaz, si late al ritmo del build o al de la petición, y compone la página respetando ese latido pieza por pieza.
- Toma un sitio real y clasifica cada página en estática pura, bajo demanda entera o estática con isla, usando el árbol de tres preguntas.
- Implementa una server island con
server:deferen una página estática y dale un contenido de reserva con elslotde fallback. - Compara el TTFB y la cacheabilidad de esa página con isla frente a la misma marcada entera como
prerender = false. - Justifica por qué la granularidad de componente supera a la de página en el caso mixto, y pon un ejemplo propio donde un solo trozo vivo habría obligado antes a servir viva toda la página.