Límites y buenas prácticas de las server islands
Las server islands son un bisturí, no un martillo. Sus fallos vienen de ignorar una de dos preguntas: el tamaño de las props —que viajan cifradas al cliente y vuelven—, la latencia del segundo viaje, la encriptación y su clave, y la combinación con adaptadores. Y sobre todo: cuándo NO usarlas —contenido crítico en el primer pintado, SEO, o una página que ya es dinámica entera—.
El tamaño de las props: pasa un id, no el mundo
La regla más importante sale directa de la lección de internals. Las props de una server island se serializan, se encriptan y se incrustan en el HTML —que quizá se cachea— y luego viajan de vuelta al servidor en la petición de la isla. Pagan peaje dos veces: engordan la página y el segundo viaje.
Pasar un objeto grande —un array de mil filas, un documento entero— es un error de rendimiento silencioso, porque no rompe nada: solo hace todo más lento y más pesado sin avisar.
La buena práctica es pasar un identificador mínimo y dejar que la isla, ya en el servidor, consulte el dato completo. La isla está más cerca de la base de datos que el HTML; que traiga ella el volumen, no que lo arrastre por el cliente.
Piensa en las props como en los argumentos de una llamada remota que se escriben en un cartel público: cuanto más cortos, mejor.
Como guía, mantén fuera de las props todo lo voluminoso o derivable:
- Colecciones enteras: pasa el
ido elslug, no el array de resultados. - Objetos anidados profundos: envía las claves que la isla necesita, no el grafo completo.
- Datos que la isla ya puede obtener: si tiene acceso a la base de datos, que los traiga ella.
- Nada sensible de más: aunque viaje cifrado, cuanto menos contenga la clausura, mejor.
<!-- Evita: props enormes viajan cifradas al cliente y regresan --><Panel server:defer filas={arrayDeMilFilas} /><!-- Prefiere: pasa un id y deja que la isla consulte el volumen --><Panel server:defer usuarioId={usuario.id} />La latencia de un segundo viaje
Una server island no está en el HTML inicial: llega después, en una segunda petición que arranca cuando la página ya cargó. Eso tiene un coste temporal ineludible —una ida y vuelta de red más el render del servidor— durante el cual se ve el fallback.
Para contenido secundario es imperceptible; para contenido que debe estar correcto en el primer instante, es un parpadeo inaceptable.
De ahí la regla: no difieras lo que debe verse ya. El titular, el precio principal por encima del pliegue, cualquier cosa que el usuario espera correcta en el primer pintado, va en el cascarón estático, no en una isla.
Presupuesta la latencia: si el fragmento puede tolerar llegar un instante tarde tras un buen fallback, es candidato; si no, no lo es. Y recuerda que ese “instante” no es fijo: en una función serverless con arranque en frío puede estirarse hasta hacerse notar, así que presupuesta para el peor caso, no para el mejor.
Encriptación, claves y adaptadores
Tres piezas operativas se combinan aquí. La encriptación de props tiene un coste de cómputo por petición —pequeño, pero real— y, sobre todo, exige la clave estable ASTRO_KEY en cuanto tengas varias instancias o reconstruyas el sitio, como vimos en la lección de internals.
El adaptador es obligatorio: la petición de la isla se ejecuta en tu servidor o en una función del borde —Node, Cloudflare, Vercel, Netlify—, así que la server island hereda las características de ese destino, incluidos sus arranques en frío, que se suman a la latencia del segundo viaje en plataformas serverless.
Hay una interacción con el número de islas que conviene vigilar. Cada server island de una página es una petición más al servidor; una página con ocho islas dispara ocho peticiones por visita, y multiplica por ocho la carga que antes era un simple servir un fichero estático.
El aislamiento es una virtud, pero no es gratis a escala: agrupa lo que comparte cadencia en una sola isla en lugar de esparcir muchas islas diminutas, y reserva el patrón para los fragmentos que de verdad lo justifican.
Cuándo NO usar una server island
El antipatrón mayor es diferir por diferir. Si toda la página ya es dinámica —renderizada por petición—, envolver un fragmento en una server island añade un viaje de red y complejidad criptográfica sin el premio que lo justificaba: el caché del cascarón, que aquí no existe porque el cascarón tampoco se cachea.
En ese caso, renderiza el fragmento en línea con el resto; la isla solo tiene sentido si aísla un trozo lento para que el resto de la respuesta fluya sin esperarlo.
Tampoco uses una isla para algo barato y estático: si el fragmento no depende ni del usuario ni del momento, hornéalo en el cascarón y ahórrate el viaje. Y no la uses para contenido crítico en el primer pintado ni relevante para SEO, por lo ya dicho.
La server island es para el cruce exacto de “cambia por usuario o por momento” y “puede permitirse llegar un instante tarde”.
En señales concretas, evita la server island cuando el fragmento:
- Debe estar correcto en el primer pintado —un titular, un precio sobre el pliegue—.
- Es contenido indexable que necesitas en el HTML inicial para SEO.
- No depende ni del usuario ni del momento: es estático y barato, hornéalo en el cascarón.
- Vive en una página ya dinámica entera, donde no hay caché de cascarón que el viaje justifique.
- Es una de muchas islas diminutas de la misma cadencia que podrían fundirse en una.
Queda un último cuidado, el de la resiliencia. Una isla puede fallar: su consulta cae, el servidor agota su tiempo, la red del segundo viaje se corta. Como su estado terminal es el fallback, ese fallback debe ser un desenlace aceptable, no un esqueleto roto para siempre.
Diseña la isla pensando que a veces no resolverá, y haz que su ausencia degrade con dignidad en lugar de dejar un hueco fantasma.
Una isla resiliente pone un límite a lo que espera y prefiere rendir su fallback antes que colgar:
---// Isla en modo servidor: cachea su salida y acota su esperaAstro.response.headers.set('Cache-Control', 'public, max-age=60');const datos = await consultarConTimeout(Astro.props.id, 800);---{datos ? <Panel datos={datos} /> : null}