Por que escolhi Astro ao invés de Next.js
O momento em que parei
Estava entregando uma landing page pra um escritório de advocacia. Cinco páginas, zero interatividade, só texto, fotos e um link pro WhatsApp. Abri o DevTools pra conferir o bundle: 287 KB de JavaScript. Pra renderizar texto estático.
O Next.js carrega o React inteiro, faz hydration da página toda, e manda o framework pro cliente mesmo quando não tem um único useState no projeto. Pra webapps isso faz sentido. Pra um site de 5 páginas, é peso morto.
Não foi uma decisão emocional. Foi um número no DevTools que não fazia sentido. Comecei a testar o Astro naquela semana.
O que o Next.js faz por debaixo dos panos
Pra entender por que migrei, preciso explicar o que o Next.js faz que você não pediu.
Quando você cria uma página em Next.js, mesmo que seja só HTML estático, o framework gera um bundle JavaScript que inclui o React runtime, o roteador do Next, e o código de hydration. Hydration é o processo de “reviver” o HTML estático no browser, conectando event listeners e estado do React. Numa página que não tem estado, não tem evento e não tem interação, isso é trabalho desperdiçado.
O bundle mínimo de um projeto Next.js fica entre 70 KB e 90 KB comprimido. Parece pouco, mas soma com cada página, cada componente, cada lib que você importa. Num site institucional com 5-8 páginas, chega fácil nos 200-300 KB de JS que o visitante baixa sem necessidade.
E tem o custo escondido: hydration bloqueia a main thread. Enquanto o React tá conectando listeners em elementos estáticos, o navegador tá ocupado. Isso impacta diretamente o INP (Interaction to Next Paint), uma das métricas que o Google usa pra ranquear.
O que mudou na prática
JS no cliente: de 287 KB pra 0
Astro gera HTML estático no build. O navegador recebe HTML puro. Sem React, sem hydration, sem bundle. O mesmo site do escritório em Astro: zero bytes de JavaScript. Literalmente.
Medi em todos os meus projetos:
- GPM2 (site tributário): se fosse Next.js, estimaria ~220 KB de JS. Em Astro: 0 KB
- Family Pilates (LP): 0 KB de JS, Lighthouse 97
- Carrega Rápido (LP densa com muitas seções e dados técnicos): 0 KB de JS, carrega em 0.9s
- Tok Final (institucional pra construtoras): 0 KB de JS, funciona até em 3G de canteiro de obra
- Soline (energia renovável com muitas imagens de campo): 0 KB de JS, Lighthouse 95+ mesmo com volume alto de fotos
São 6 projetos em produção. Nenhum manda JavaScript pro cliente, e todos ficam acima de 95 no Lighthouse sem otimização manual.
Lighthouse sem forçar
Com Next.js, eu passava tempo otimizando: lazy loading manual, dynamic imports, bundle splitting, preconnect pra fontes externas, prefetch seletivo. Era uma checklist de 15 itens pra chegar num Lighthouse de 90.
Com Astro, a arquitetura já entrega 95+ por padrão. O tempo que eu gastava otimizando o framework agora gasto no conteúdo e no design do site. A ferramenta parou de atrapalhar.
Component Islands quando precisa
Zero JS não significa zero interatividade. O Family Pilates tem um carrossel de depoimentos. Só esse componente carrega JavaScript. O resto da página (hero, serviços, sobre, CTA) continua estático.
É o conceito de Islands Architecture: a página é um oceano de HTML estático com ilhas de interatividade. Cada ilha hidrata independentemente. O carrossel carrega 12 KB de JS. O resto: zero.
No Next.js, se um componente precisa de JS, o framework inteiro vai junto. Não tem como isolar. No Astro, a diretiva client:visible faz o componente carregar JS só quando entra no viewport. Antes disso, é HTML inerte.
Build time
Next.js num site de 8 páginas: 15-30 segundos de build. Astro: 3-8 segundos. Parece irrelevante, mas quando você tá iterando no design e fazendo build a cada 2 minutos, a diferença acumula. No final de um dia de trabalho, são 20-30 minutos a menos esperando terminal.
Tem outro ponto que pouca gente menciona: o build do Next.js fica mais lento conforme o projeto cresce porque ele precisa processar o grafo de dependências do React inteiro, mesmo pra páginas que não usam nenhum componente dinâmico. O Astro trata cada página como independente — o build de uma página de 200 linhas leva o mesmo tempo seja num projeto de 5 ou 50 páginas.
DX (Developer Experience)
Astro usa uma sintaxe própria (.astro) que parece uma mistura de HTML com JSX. O frontmatter fica no topo do arquivo entre ---, e o template fica embaixo. É mais simples que o modelo de pages/components do Next.js porque não tem server components, client components, API routes, middleware — é só arquivo estático com template.
Isso tem trade-off: pra quem vem de React, leva 1-2 dias pra se acostumar com a sintaxe. Mas depois que encaixa, é mais produtivo pra conteúdo estático.
Outra vantagem prática: o Astro aceita componentes de qualquer framework. Se você tem um componente React pronto, usa ele dentro de um arquivo .astro sem reescrever nada. Mesma coisa com Svelte, Vue ou Solid. Isso significa que migrar de Next.js pra Astro não exige jogar fora tudo que já existe — dá pra trazer componentes isolados e usar com client:load ou client:visible conforme a necessidade.
Onde o Astro não serve
Não uso Astro pra webapps. Preciso ser claro sobre isso porque a decisão não é “Astro é melhor”, é “Astro é melhor pra um tipo de projeto”.
O AutoPars (marketplace com 3 painéis, autenticação, estado compartilhado, real-time, 5 integrações) é React com TypeScript. Não faria sentido em Astro. O sistema tem carrinho de compras com estado persistente, dashboard admin com dados em tempo real, e formulários com validação complexa. Tudo isso precisa de JavaScript no cliente.
O Mariah (controle de encomendas com dashboard financeiro) também é React. Dashboard com filtros, gráficos e atualização em tempo real não funciona em HTML estático.
O FitPlan (plataforma pra academias com 6 painéis) é React. Sistema com treinos interativos, vídeos, notificações e avaliações físicas precisa de uma SPA completa.
Se o projeto tem login, estado, formulários complexos e navegação interna, React é a ferramenta certa. Astro não foi feito pra isso e não tenta ser.
A decisão que uso hoje
Antes de começar qualquer projeto, faço três perguntas:
1. O usuário faz login? Se sim, React. Se não, Astro.
2. O conteúdo muda depois que a página carrega? Se dados atualizam em tempo real, se tem formulário com estado, se tem interação além de scroll e clique em link — React. Se a página é a mesma pra todo mundo que acessa — Astro.
3. SEO é prioridade? Se sim, Astro ganha por padrão. React precisa de SSR ou SSG configurado pra ser indexado corretamente. Astro já nasce assim. É por isso que o AutoPars precisou de uma LP separada em Astro como camada de SEO — a SPA React não indexa bem sozinha.
Se o projeto precisa dos dois, faço dois projetos separados. Cada um na stack certa. A complicação estava em usar Next.js pra tudo por inércia.
Números resumidos
| Métrica | Next.js (site estático) | Astro |
|---|---|---|
| JS no cliente | 180-300 KB | 0 KB |
| Lighthouse (sem otimizar) | 70-85 | 95+ |
| Tempo de build | 15-30s | 3-8s |
| Complexidade de config | Média | Baixa |
| Hydration | Obrigatória | Opcional (Islands) |
| SEO nativo | Precisa de SSR/SSG | Sim |
E o Next.js App Router?
Desde o App Router (Next.js 13+), o Next melhorou pra conteúdo estático com React Server Components. Mas ainda carrega o runtime do React pro cliente quando qualquer componente usa 'use client'. E na prática, quase todo projeto Next acaba com pelo menos um 'use client' — um header interativo, um formulário, um toggle.
O Astro resolve isso de forma mais limpa: zero JS é o padrão, e você opta por JS componente a componente. É filosofia invertida.
Na prática, testei migrar um projeto de 6 páginas do App Router pro Astro. O bundle caiu de 112 KB pra 0. O Lighthouse subiu de 88 pra 98. E o tempo de build caiu pela metade. O App Router melhorou o Next.js pra conteúdo estático, mas ainda não compete com uma ferramenta que nasceu pra isso.
Pra quem é esse post
Se você é dev e ainda usa Next.js pra landing page, abre o DevTools agora e olha o bundle. Filtra por JS na aba Network. O número vai te incomodar.
Se você é dono de empresa e o dev te entregou um site institucional que demora 3 segundos pra carregar, pergunta pra ele: quanto JavaScript tá sendo mandado pro navegador? Se a resposta for “mas precisa do React pra…”, pergunta pra que exatamente. Se for pra renderizar texto e imagem, não precisa.
O melhor JavaScript é o que não precisa existir. A pergunta certa nunca foi “qual framework usar”. A pergunta é “esse projeto precisa de um framework JavaScript no cliente?”. Na maioria dos sites institucionais e landing pages, a resposta é não. Astro só torna essa resposta mais fácil de implementar.