Puntos clave
- El renderizado híbrido de Astro mantiene la mayor parte de la página estática, mientras que Server Islands solo transmite los elementos dinámicos desde el servidor cuando se solicitan.
- Las «Server Islands» necesitan un adaptador SSR de verdad, como @astrojs/node, y un servidor persistente, ya que los arranques en frío sin servidor interrumpen las solicitudes de las «islas» bajo demanda.
- Cloudways Velocity detecta automáticamente la configuración predeterminada del framework Node.js a partir de los archivos de tu proyecto, así que puedes desplegarlo directamente desde GitHub sin tener que configurar tú mismo Nginx, PM2 o SSL.
- El proyecto de demostración completo, un panel de control bursátil en tiempo real creado con Astro Server Islands, está disponible en GitHub para que lo clones y lo reutilices.
Localhost es fácil. Siempre lo es. Creas tus componentes, ejecutas el script de desarrollo de Astro y todo se carga al instante.
Entonces intentas publicar esa aplicación dinámica en Internet. De repente, tienes que decidir qué infraestructura usar, y las opciones estándar suelen dejarte frustrado.
O bien alquilas un servidor Linux sin nada instalado y te pasas el fin de semana haciendo de administrador de sistemas sin cobrar, o bien subes el código a una plataforma de borde sin servidor que pone tu app en modo de suspensión en cuanto la gente deja de usarla.
Si estás conectando datos dinámicos en tiempo real con Astro Server Islands, el alojamiento sin servidor efímero te va a dar un buen dolor de cabeza. Necesitas un backend persistente.
Voy a explicarte paso a paso cómo crear un panel de control bursátil rápido con el renderizado híbrido de Astro y cómo implementarlo directamente en un servidor persistente Node.js (Velocity) gestionado por Cloudways. Sin configuraciones de Nginx que depurar. Sin arranques en frío sin servidor. Solo un alojamiento Astro fiable.
Implementa Astro sin arranques en frío
. Ejecuta tu aplicación Astro SSR y tus Server Islands en un servidor Cloudways Velocity persistente, sin periodo de inactividad «serverless» ni picos de latencia.
Entender los modos de renderizado de Astro
Veamos los dos extremos del renderizado web y por qué ninguno de ellos es perfecto para una aplicación dinámica estándar.
Por un lado, tienes la generación de sitios estáticos (SSG) pura y dura. Obtienes archivos HTML planos y una velocidad insuperable, pero el contenido queda fijado en el momento de la compilación. No puede mostrar a un usuario que haya iniciado sesión su propio panel de control.
Por eso, al final la gente acaba optando por el renderizado del lado del servidor (SSR) a página completa. El servidor genera la página completa desde cero con cada solicitud.
Pero aquí está el problema. El SSR a página completa arruina tu «Time to First Byte». Los usuarios se quedan ahí mirando una pantalla en blanco mientras el servidor espera a que se resuelva una consulta lenta en la base de datos o una API de terceros antes de poder enviar ni un solo byte de HTML.
El renderizado híbrido de Astro soluciona este cuello de botella. Mantiene el núcleo de tu web estático, a la vez que te permite aplazar de forma selectiva la visualización de componentes específicos para que se rendericen en el servidor una vez que la página inicial ya se haya cargado.
Cómo funcionan las «Server Islands» de Astro (server:defer)
Esta ejecución selectiva de los servidores es precisamente la razón por la que las «Server Islands» son tan útiles.
En lugar de ralentizar toda una página solo para cargar un widget en tiempo real, las «Server Islands» dividen la carga en dos partes. El navegador recibe el diseño estático al instante. Después, una solicitud interna en segundo plano recupera el componente dinámico y lo sustituye.
Usaré la directiva `server:defer` para que esto funcione. Este es el código:
---
import Layout from '../layouts/Layout.astro';
import StockTicker from '../components/StockTicker.astro';
import TickerSkeleton from '../components/TickerSkeleton.astro';
---
<Layout>
<h1>Market Overview</h1>
<!-- Server Island with Fallback -->
<StockTicker server:defer>
<TickerSkeleton slot="fallback" />
</StockTicker>
</Layout>
La lógica que hay detrás de esto es súper importante. Astro omite el componente <StockTicker/> durante la carga inicial. Inserta un marcador de posición <TickerSkeleton slot=»fallback»/> para que la pantalla no se mueva de un lado a otro, y luego transmite los datos reales cuando están listos.
Para ejecutar componentes dinámicos bajo demanda es imprescindible tener un adaptador de servidor activo, como @astrojs/node.
Node.js sin servidor frente a Node.js persistente para Astro Hosting
Si alojaras esto en una plataforma estándar sin servidor, te encontrarías con problemas casi de inmediato.
Los proveedores de servicios sin servidor cierran tu aplicación cuando el tráfico web baja. Cuando un nuevo usuario solicita una «Server Island», la plataforma tiene que iniciar una instancia de función completamente nueva desde cero, cargar el entorno de ejecución de Node y, a continuación, ejecutar tu componente. Ese retraso se conoce como «arranque en frío».
Si tu sitio recibe 150 visitas a la vez, la plataforma intenta poner en marcha 600 instancias independientes para dar respuesta a las solicitudes paralelas de Server Island. Cada una de ellas paga ese «impuesto de arranque en frío» por separado.
Este cuello de botella en las invocaciones es precisamente la razón por la que necesitas un entorno Node persistente para Server Islands.
Un servidor dedicado nunca pone en suspensión tu proceso de Astro. Se mantiene activo. Como el código de ejecución ya está cargado en la memoria, una solicitud a Server Island se resuelve en milisegundos en lugar de segundos.
Usar un entorno gestionado como Cloudways Velocity te ofrece esa potencia constante sin que tengas que configurar manualmente tú mismo el servidor Linux subyacente.
Mantén tus «Server Islands» siempre calientes
El alojamiento gestionado de Node.js de Cloudways mantiene tu adaptador Astro en funcionamiento las 24 horas del día, por lo que las solicitudes en segundo plano de las «Server Islands» nunca se enfrentan a un arranque en frío.
Mini proyecto: Crear un panel de control bursátil
Voy a crear un panel de control bursátil minimalista. Voy a escribir una aplicación Astro que gestione el renderizado híbrido y utilice Server Islands con el adaptador Node.
Configuración del proyecto local
Lo primero que voy a hacer es configurar mi espacio de trabajo local.
Para esta demostración estoy usando mi portátil del trabajo, que tiene restricciones informáticas, así que no puedo ejecutar el instalador estándar de Node. En su lugar, voy a descargar la versión .zip con el binario independiente de Node.js en mi ordenador.
Después de descomprimir la carpeta de Node, le diré al Símbolo del sistema dónde está en mi ordenador. Para ello, ejecutaré este comando con la ruta exacta:
set PATH=%PATH%;C:\Users\abdulrehman\Downloads\node-v24.18.0-win-x64\node-v24.18.0-win-x64
Genial, ahora ya puedo ejecutar comandos de Node y npm.
A continuación, voy a crear una carpeta para el proyecto en mi escritorio.
cd C:\Users\abdulrehman\Desktop mkdir cw-astro-stock-dashboard cd cw-astro-stock-dashboard npm create astro@latest . -- --template minimal --no-install --no-git --typescript strictest

Ahora voy a instalar las dependencias. Necesito el adaptador oficial de Node para ejecutar esto como un servidor independiente.
npm install

npm install @astrojs/node

También tengo que configurar Astro para que utilice ese adaptador. Voy a abrir mi editor y a modificar el archivo astro.config.mjs:
// astro.config.mjs
import { defineConfig } from 'astro/config';
import node from '@astrojs/node';
export default defineConfig({
output: 'server',
adapter: node({
mode: 'standalone',
}),
});

Y ya está. Mi entorno local ya está totalmente operativo en este momento.
Creación de la «isla de servidores» dinámica
Para probar la persistencia en condiciones reales, mantener la capacidad de respuesta de un componente dinámico es la prueba de estrés perfecta. Voy a abrir mi editor y crear un archivo llamado src/components/StockTicker.astro. Voy a pegar mi script personalizado:
---
// src/components/StockTicker.astro
// Simulate a database or API delay
await new Promise((resolve) => setTimeout(resolve, 800));
const stocks = [
{ symbol: 'AAPL', name: 'Apple Inc.', price: '224.23', change: '+1.45%' },
{ symbol: 'NVDA', name: 'NVIDIA Corp.', price: '128.50', change: '+3.12%' },
{ symbol: 'MSFT', name: 'Microsoft', price: '448.90', change: '-0.22%' },
{ symbol: 'AMZN', name: 'Amazon.com', price: '186.40', change: '+0.88%' },
];
const timestamp = new Date().toLocaleTimeString();
---
<div style="background: #111827; border: 1px solid #374151; border-radius: 8px; padding: 1.5rem; color: #f9fafb; font-family: sans-serif;">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem;">
<h3 style="margin: 0;">Live Market Indices</h3>
<span style="font-size: 0.8rem; background: #065f46; color: #34d399; padding: 0.2rem 0.6rem; border-radius: 4px;">Updated: {timestamp}</span>
</div>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 1rem;">
{stocks.map((stock) => (
<div style="background: #1f2937; padding: 1rem; border-radius: 6px; display: flex; flex-direction: column; gap: 0.25rem;">
<span style="font-weight: bold;">{stock.symbol}</span>
<span style="font-size: 1.2rem;">${stock.price}</span>
<span style={`font-weight: 500; color: ${stock.change.startsWith('+') ? '#34d399' : '#f87171'};`}>
{stock.change}
</span>
</div>
))}
</div>
</div>

Ahora tengo que crear el esqueleto provisional para que la página no se vea mal mientras se carga. Voy a crear un archivo llamado TickerSkeleton.astro:
---
// src/components/TickerSkeleton.astro
---
<div style="background: #111827; border: 1px solid #374151; border-radius: 8px; padding: 1.5rem; font-family: sans-serif;">
<div style="height: 24px; width: 180px; background: #1f2937; border-radius: 4px; margin-bottom: 1rem;"></div>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 1rem;">
<div style="height: 80px; background: #1f2937; border-radius: 6px;"></div>
<div style="height: 80px; background: #1f2937; border-radius: 6px;"></div>
<div style="height: 80px; background: #1f2937; border-radius: 6px;"></div>
<div style="height: 80px; background: #1f2937; border-radius: 6px;"></div>
</div>
</div>

Ahora, lo montó todo en src/pages/index.astro:
---
// src/pages/index.astro
import StockTicker from '../components/StockTicker.astro';
import TickerSkeleton from '../components/TickerSkeleton.astro';
---
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Astro Stock Dashboard</title>
</head>
<body style="background: #030712; color: #f3f4f6; font-family: system-ui, sans-serif; max-width: 800px; margin: 2rem auto; padding: 0 1rem;">
<header style="border-bottom: 1px solid #1f2937; padding-bottom: 1rem; margin-bottom: 2rem;">
<h1 style="margin: 0;">Market Dashboard</h1>
<p style="color: #9ca3af;">Static layout shell delivered instantly via cached HTML.</p>
</header>
<main>
<StockTicker server:defer>
<TickerSkeleton slot="fallback" />
</StockTicker>
</main>
</body>
</html>

Para probar lo que he creado localmente, voy a compilar la versión independiente y a ejecutar el archivo de entrada.
npm run build

node ./dist/server/entry.mjs
Tras ejecutar el comando de Node, la terminal muestra un mensaje confirmando que el servidor está a la escucha.

Para ver cómo funciona la aplicación, abro mi navegador y voy a http://localhost:4321.

La página carga al instante un encabezado estático, junto con el marcador de posición del esqueleto.
Esto es justo lo que esperaba ver. Significa que Astro ha enviado el shell estático y está esperando la solicitud en segundo plano.
Cuando acaba el retraso de 800 ms, el esqueleto desaparece. En su lugar, ahora puedo ver los datos bursátiles en tiempo real.
El miniproyecto funciona perfectamente en mi ordenador. Ahora puedo subir este código a Git e implementarlo en Cloudways Velocity.
Subir el proyecto a GitHub
Antes de subirlo, voy a abrir mi archivo package.json y añadiré manualmente un script de inicio. Debería quedar exactamente así:
"scripts": {
"start": "node ./dist/server/entry.mjs"
}
Mi código actualizado quedará así:
{
"name": "cw-astro-stock-dashboard",
"type": "module",
"version": "1.0.0",
"scripts": {
"dev": "astro dev",
"build": "astro build",
"preview": "astro preview",
"start": "node ./dist/server/entry.mjs"
},
"dependencies": {
"@astrojs/node": "^9.0.0",
"astro": "^5.0.0"
}
}

El comando «start» es fundamental. Cloudways busca esta palabra clave exacta al configurar el servidor de producción.
Voy a entrar en GitHub y crearé un nuevo repositorio. Lo llamaré «cw-velocity-astro-ssr».

Después volveré a la línea de comandos y subiré el proyecto a mi repositorio de GitHub:
git init git add . git commit -m "Initial commit: Astro SSR Dashboard with Server Islands" git branch -M main git remote add origin https://github.com/abdulrehman293/cw-velocity-astro-ssr git push -u origin main
Ahora que ya he subido mi código a GitHub, es hora de crear mi servidor Node.js en Cloudways.

Implementación del miniproyecto en Cloudways Velocity
Implementar una aplicación Astro SSR personalizada en servidores VPS «bare-metal» suele implicar configurar Nginx como proxy inverso, mantener PM2 en funcionamiento y ocuparte de los certificados SSL.
Cloudways Velocity se encarga por sí solo de esas tareas del lado del servidor. Ofrece un entorno Node.js gestionado en el que la configuración del servidor subyacente ya está lista para ti.
Olvídate de DevOps, lanza tu aplicación más rápido
Cloudways Velocity detecta automáticamente tu adaptador Astro Node y se encarga de Nginx, PM2 y SSL por ti.
Volvamos a la implementación. Abriré la consola de Cloudways, seleccionaré Velocity y haré clic en «Empezar».

Para esta implementación, voy a elegir el plan Starter, que es más que suficiente para esta demostración.

A continuación, conecto mi cuenta de GitHub, selecciono mi repositorio cw-velocity-astro-ssr y hago clic en «Continuar».


Ahora Cloudways se encarga de elegirlo todo automáticamente por mí. Por ejemplo, busca el archivo «package.json» en la carpeta raíz del proyecto. A partir de ahí, lee las dependencias, detecta el adaptador de Node y selecciona automáticamente la configuración predeterminada adecuada para el framework.

No hace falta que cree comandos de inicio personalizados ni que configure PM2 a mano. La plataforma se encarga de todo eso como parte del proceso de implementación.
Así que, por ahora, voy a hacer clic en «Implementar ahora» y voy a dejar que se complete la implementación.

Ahora que la app ya está implementada, voy a volver a la pestaña «Resumen» de la aplicación y copiaré la URL de la aplicación. La abriré en el navegador para echar un vistazo al sitio.


El encabezado de la página estática se carga al instante, igual que en el entorno local.

En la pestaña «Red», puedo ver cómo se va recibiendo la solicitud en segundo plano a /_server-islands/StockTicker.

Cuando se resuelve la solicitud, los datos bursátiles en tiempo real aparecen al instante.
Y con esto, ya estoy disfrutando de una instancia de Astro SSR de verdad, siempre activa. Sin tiempos de espera en la conexión. Sin arranques en frío.
Conclusión
Con esto termina esta guía de implementación de Astro. He explicado por qué un entorno Node.js persistente puede ser más adecuado para el renderizado híbrido, sobre todo cuando la aplicación se basa en la transmisión de Server Islands sin retrasos por arranques en frío.
También he creado localmente un panel híbrido de Astro, he probado el proyecto, lo he subido a GitHub y, a continuación, he implementado la aplicación terminada utilizando el alojamiento gestionado de Node.js de Cloudways (Velocity).
El proyecto completo está disponible en mi GitHub por si quieres usarlo como punto de partida para tu propia aplicación Astro. Si tienes algún problema con los pasos de configuración o implementación, no dudes en dejar una pregunta en los comentarios.
P. ¿Para qué sirve exactamente Astro SSR?
Los desarrolladores usan Astro SSR para crear funcionalidades dinámicas en el backend. Te permite comprobar cookies de autenticación, consultar bases de datos u obtener datos en tiempo real en el momento de la solicitud, en lugar de recargar toda la página.
P. ¿Cuál es la diferencia entre islas de cliente e islas de servidor?
Las islas de cliente ejecutan código de interfaz de usuario interactivo en el navegador mediante JavaScript. Las islas de servidor ejecutan la lógica de los componentes completamente en el servidor y simplemente envían fragmentos HTML planos al navegador.
P. ¿Por qué Astro requiere un adaptador SSR para Server Islands?
El alojamiento de archivos estáticos no permite la ejecución de código de backend. Dado que Server Islands activa código en el servidor cada vez que un usuario solicita la página, se necesita un adaptador como @astrojs/node para proporcionar un entorno de servidor real.
P. ¿Es mejor usar Node.js persistente que el modelo sin servidor para esto?
Sí. Las páginas con varias «Server Islands» generan múltiples solicitudes HTTP en paralelo. En el modelo sin servidor, esto provoca arranques en frío muy lentos. Un servidor persistente se mantiene activo en la RAM y gestiona al instante las solicitudes entrantes de las «islands».
Start Growing with Cloudways Today.
Our Clients Love us because we never compromise on these
[email protected]
Abdul es un experto en tecnología, aficionado al café y al marketing creativo al que le encanta estar al día de las últimas actualizaciones de software y aparatos tecnológicos. También es un hábil escritor técnico capaz de explicar conceptos complejos de forma sencilla para un público amplio. Abdul disfruta compartiendo sus conocimientos sobre el sector de la Nube a través de manuales de usuario, documentación y entradas de blog.