Pontos-chave
- A renderização híbrida do Astro mantém a maior parte da página estática, enquanto as Server Islands transmitem apenas as partes dinâmicas do servidor quando solicitadas.
- As Server Islands precisam de um adaptador SSR a sério, como o @astrojs/node, e de um servidor persistente, já que os arranques a frio em ambientes sem servidor (serverless) interrompem os pedidos às ilhas sob demanda.
- O Cloudways Velocity deteta automaticamente a predefinição do framework Node.js a partir dos ficheiros do teu projeto, para que possas fazer a implementação diretamente do GitHub sem teres de configurar o Nginx, o PM2 ou o SSL.
- O projeto de demonstração completo, um painel de mercado bolsista em tempo real construído com as Server Islands do Astro, está disponível no GitHub para clonares e reutilizares.
O localhost é fácil. É sempre assim. Crias os teus componentes, executas o script de desenvolvimento do Astro e tudo carrega num instante.
Depois, quando tentas mesmo colocar essa aplicação dinâmica na Internet, de repente tens de tomar uma decisão sobre a infraestrutura, e as opções padrão costumam deixar-te frustrado.
Ou alugas um servidor Linux vazio e passas o fim de semana a fazer de administrador de sistemas sem receber nada, ou colocas o código numa plataforma de edge sem servidor que coloca a tua aplicação em modo de suspensão assim que as pessoas deixarem de a usar.
Se estiveres a ligar dados dinâmicos em tempo real usando o Astro Server Islands, a hospedagem sem servidor efémera vai dar-te uma enorme dor de cabeça. Precisas de um backend persistente.
Vou explicar-te como criar um painel rápido do mercado de ações com a renderização híbrida do Astro e implementá-lo diretamente num servidor Node.js (Velocity) gerido pela Cloudways e persistente. Sem configurações do Nginx para depurar. Sem arranques a frio sem servidor. Apenas alojamento Astro de confiança.
Implementa o Astro sem os arranques a frio
Executa a tua aplicação Astro SSR e as Server Islands num servidor Cloudways Velocity persistente, sem o modo de suspensão do servidorless e sem picos de latência.
Compreender os modos de renderização do Astro
Vamos ver os dois extremos da renderização web e porque é que nenhum deles é perfeito para uma aplicação dinâmica padrão.
Por um lado, tens a Geração de Sites Estáticos (SSG) pura. Ficas com ficheiros HTML simples e uma velocidade imbatível, mas o conteúdo fica fixo no momento da compilação. Não consegue mostrar a um utilizador que iniciou sessão o seu próprio painel de controlo.
Por isso, as pessoas acabam por optar pela renderização do lado do servidor (SSR) em página inteira. O servidor gera a página inteira de raiz a cada pedido.
Mas aqui está o problema. O SSR de página inteira estraga o teu «Time to First Byte». Os utilizadores ficam ali a olhar para um ecrã branco enquanto o servidor aguarda uma consulta lenta à base de dados ou uma API de terceiros antes de poder enviar um único byte de HTML.
A renderização híbrida do Astro resolve este estrangulamento. Mantém o núcleo do teu site estático, ao mesmo tempo que te permite adiar seletivamente a renderização de componentes específicos no servidor, para que sejam renderizados depois de a página inicial já ter sido carregada.
Como funcionam as «Server Islands» do Astro (server:defer)
É precisamente esta execução seletiva do servidor que torna as «Server Islands» tão úteis.
Em vez de tornar toda a página lenta só para carregar um widget dinâmico, as «Server Islands» dividem o carregamento em duas partes. O navegador recebe o layout estático instantaneamente. Depois, um pedido interno em segundo plano vai buscar o componente dinâmico e substitui-o.
Vou usar a diretiva «server:defer» para que isto aconteça. Eis como fica o 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>
A lógica aqui é extremamente importante. O Astro ignora o componente <StockTicker/> durante o carregamento inicial. Ele insere um placeholder <TickerSkeleton slot=”fallback”/> para que o ecrã não fique a saltar, e depois transmite os dados reais quando estiver tudo pronto.
Executar componentes dinâmicos sob demanda requer obrigatoriamente um adaptador de servidor ativo, como o @astrojs/node.
Node.js sem servidor vs. Node.js persistente para a Astro Hosting
Se fosses hospedar isto numa plataforma sem servidor padrão, irias deparar-te com problemas quase de imediato.
Os fornecedores de serviços sem servidor encerram a tua aplicação quando o tráfego web diminui. Quando um novo utilizador solicita um Server Island, a plataforma tem de iniciar uma instância de função totalmente nova a partir do zero, carregar o runtime do Node e, só depois, executar o teu componente. Esse atraso chama-se «arranque a frio».
Se o teu site receber 150 visitas ao mesmo tempo, a plataforma tenta ativar 600 instâncias separadas para dar resposta aos pedidos paralelos do Server Island. Cada uma delas paga individualmente esse custo de arranque a frio.
Este estrangulamento nas chamadas é precisamente a razão pela qual precisas de um ambiente Node persistente para as Server Islands.
Um servidor dedicado nunca coloca o teu processo Astro em modo de suspensão. Ele mantém-se ativo. Como o código de execução já está carregado na memória, um pedido do Server Island é processado em milissegundos, em vez de segundos.
Usar um ambiente gerido como o Cloudways Velocity dá-te essa potência constante sem te obrigar a configurar manualmente o servidor Linux subjacente.
Mantém as tuas Server Islands sempre ativas
A hospedagem Node.js gerida pela Cloudways mantém o teu adaptador Astro a funcionar 24 horas por dia, para que os pedidos em segundo plano das Server Islands nunca tenham de passar por um arranque a frio.
Miniprojeto: Criar um painel de controle do mercado de ações
Vou criar um painel de controle minimalista para o mercado de ações. Vou escrever um aplicativo Astro que lida com renderização híbrida e usa o Server Islands com o adaptador Node.
Configurar o projeto local
A primeira coisa que vou fazer é configurar o meu espaço de trabalho local.
Estou a usar o meu portátil do trabalho para esta demonstração, que tem restrições de TI, por isso não consigo executar o instalador padrão do Node. Em vez disso, vou descarregar a versão .zip do binário autónomo do Node.js para o meu computador.
Depois de descompactar a pasta do Node, vou indicar ao Prompt de Comandos onde ela está na minha máquina. Para isso, vou executar este comando com o caminho exato:
set PATH=%PATH%;C:\Users\abdulrehman\Downloads\node-v24.18.0-win-x64\node-v24.18.0-win-x64
Ótimo, agora já posso executar comandos do Node e do npm.
A seguir, vou criar uma pasta de projeto no meu ambiente de trabalho.
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

A seguir, vou instalar as dependências. Preciso do adaptador oficial do Node para executar isto como um servidor autónomo.
npm install

npm install @astrojs/node

Também preciso de configurar o Astro para usar esse adaptador. Vou abrir o meu editor e ajustar o ficheiro 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',
}),
});

É isso mesmo. O meu ambiente local já está totalmente operacional nesta fase.
Criar a «Ilha de Servidores Dinâmica»
Para testar a persistência em condições reais, manter um componente dinâmico a responder é o teste de carga perfeito. Vou abrir o meu editor e criar um ficheiro src/components/StockTicker.astro. Vou inserir o meu 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>

A seguir, preciso de criar o esqueleto provisório para que a página não pareça avariada enquanto carrega. Vou criar um ficheiro chamado 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>

Agora, vou juntar tudo no ficheiro 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 testar o que criei localmente, vou compilar a versão autónoma e executar o ficheiro de entrada.
npm run build

node ./dist/server/entry.mjs
Depois de executar o comando node, o terminal mostra uma confirmação de que o servidor está a escutar.

Para ver a aplicação a funcionar, abro o meu navegador e vou a http://localhost:4321.

A página carrega um cabeçalho estático num instante, juntamente com o espaço reservado para o esqueleto.
É exatamente isto que eu esperava ver. Significa que o Astro apresentou a interface estática e está à espera do pedido em segundo plano.
Quando o atraso de 800 ms acabar, o esboço desaparece. Em vez disso, agora consigo ver os dados em tempo real do mercado bolsista.
O miniprojeto está a funcionar na perfeição no meu computador. Agora posso enviar este código para o Git e implementá-lo no Cloudways Velocity.
Enviar o projeto para o GitHub
Antes de fazer o envio, vou abrir o meu ficheiro package.json e adicionar manualmente um script de arranque. Deve ficar exatamente assim:
"scripts": {
"start": "node ./dist/server/entry.mjs"
}
O meu código atualizado vai ficar assim:
{
"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"
}
}

O comando «start» é fundamental. A Cloudways procura exatamente esta palavra-chave ao configurar o servidor de produção.
Vou ao GitHub e, depois, vou criar um novo repositório. Vou chamá-lo de cw-velocity-astro-ssr.

Depois, volto ao meu prompt de comandos e envio o projeto para o meu repositório do 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
Com o meu código carregado no GitHub, está na hora de criar o meu servidor Node.js no Cloudways.

Implementar o mini-projeto no Cloudways Velocity
Implementar uma aplicação Astro SSR personalizada em servidores VPS bare-metal normalmente implica configurar o Nginx como proxy reverso, manter o PM2 a funcionar e tratar dos certificados SSL.
O Cloudways Velocity trata dessas tarefas do lado do servidor por si próprio. Oferece um ambiente Node.js gerido, onde a configuração do servidor subjacente é tratada por ti.
Esquece o DevOps, lança mais depressa
O Cloudways Velocity deteta automaticamente o teu adaptador Astro Node e trata do Nginx, do PM2 e do SSL por ti.
De volta à implementação. Vou abrir a consola do Cloudways, selecionar o Velocity e, em seguida, clicar em «Começar».

Para esta implementação, vou escolher o plano Starter, que é mais do que suficiente para esta demonstração.

A seguir, ligo a minha conta do GitHub, seleciono o meu repositório cw-velocity-astro-ssr e clico em Continuar.


Agora, o Cloudways vai escolher tudo automaticamente por mim. Por exemplo, procura o ficheiro package.json na raiz do projeto. A partir daí, lê as dependências, deteta o adaptador Node e seleciona automaticamente a predefinição de framework adequada.

Não preciso de criar comandos de arranque personalizados nem de configurar o PM2 manualmente. A plataforma trata disso tudo como parte da implementação.
Por isso, vou clicar em «Implementar agora» e deixar que a implementação termine.

Agora que a aplicação está implementada, vou voltar ao separador «Visão geral» da aplicação e copiar o URL da aplicação. Vou abri-lo no navegador para ver como fica o site.


O cabeçalho da página estática carrega instantaneamente, tal como acontecia no ambiente local.

No separador «Rede», consigo ver a solicitação em segundo plano para /_server-islands/StockTicker a ser recebida.

Quando a solicitação é resolvida, os dados de cotações em tempo real aparecem imediatamente no lugar certo.
E com isto, estou a experimentar uma instância Astro SSR verdadeira e sempre ativa. Sem tempos de espera de ligação. Sem arranques a frio.
Conclusão
E assim chega ao fim este guia de implementação do Astro. Expliquei porque é que um ambiente Node.js persistente pode ser mais adequado para a renderização híbrida, especialmente quando a aplicação depende do streaming de Server Islands sem atrasos de arranque a frio.
Também criei um painel híbrido do Astro localmente, testei o projeto, enviei-o para o GitHub e, depois, implementei a aplicação final usando o Alojamento Node.js Gerido da Cloudways (Velocity).
O projeto completo está disponível no meu GitHub, caso queiras usá-lo como ponto de partida para a tua própria aplicação Astro. Se tiveres algum problema com os passos de configuração ou implementação, não hesites em deixar uma pergunta nos comentários.
P: Para que serve exatamente o Astro SSR?
Os desenvolvedores usam o Astro SSR para criar funcionalidades dinâmicas de backend. Ele permite verificar cookies de autenticação, consultar bancos de dados ou buscar dados em tempo real no momento da requisição, em vez de reconstruir todo o site.
P. Qual é a diferença entre Client Islands e Server Islands?
As Client Islands executam código de interface do utilizador interativo no navegador, utilizando JavaScript. As Server Islands executam a lógica dos componentes inteiramente no servidor e limitam-se a enviar trechos de HTML simples de volta para o navegador.
P. Por que é que o Astro precisa de um adaptador SSR para as Server Islands?
O alojamento de ficheiros estáticos não consegue executar código backend. Como as Server Islands acionam código no servidor sempre que um utilizador pede a página, precisas de um adaptador como o @astrojs/node para criar um ambiente de servidor a sério.
P. O Node.js persistente é melhor do que o serverless para isto?
Sim. As páginas com várias «Server Islands» desencadeiam várias solicitações HTTP em paralelo. No serverless, isto causa arranques a frio muito pesados. Um servidor persistente fica ativo na RAM e lida imediatamente com as solicitações das «islands» que chegam.
Start Growing with Cloudways Today.
Our Clients Love us because we never compromise on these
[email protected]
O Abdul é um profissional de marketing experiente em tecnologia, movido a café e criativo, que adora manter-se a par das últimas actualizações de software e gadgets tecnológicos. É também um escritor técnico competente que consegue explicar conceitos complexos de forma simples para um público alargado. Abdul gosta de partilhar os seus conhecimentos sobre a indústria da nuvem através de manuais de utilizador, documentação e publicações em blogues.