Renderização no Servidor com Preact
Se você já desenvolveu aplicações com React e Vite, provavelmente já compreende a renderização no cliente. O navegador baixa um bundle JavaScript, o executa e constrói o DOM. Funciona, mas usuários em conexões lentas ficam olhando para uma tela em branco enquanto o bundle carrega. A Renderização no Servidor (SSR) com Preact resolve esse problema enviando HTML pronto para exibição diretamente do servidor. O reduzido footprint de runtime do Preact torna esse tradeoff especialmente atraente para aplicações focadas em performance.
Este artigo explica como o SSR do Preact funciona, quais ferramentas estão envolvidas e como a hidratação conecta o HTML renderizado no servidor a uma aplicação interativa em execução.
Principais Aprendizados
- O SSR do Preact renderiza sua árvore de componentes para uma string HTML no servidor, entregando aos usuários conteúdo visível antes mesmo de qualquer JavaScript ser executado.
- O pacote
preact-render-to-stringfornece APIs de renderização síncrona, assíncrona e em streaming para atender a diferentes necessidades de aplicação. - A hidratação adiciona interatividade ao HTML renderizado no servidor usando
hydrateem vez derender, preservando o DOM existente. - Um fluxo de trabalho baseado em Vite com
@preact/preset-viteé o padrão moderno para novos projetos Preact com suporte a SSR. - Evite incompatibilidades de hidratação mantendo a saída do servidor e do cliente consistentes — sem timestamps, IDs aleatórios ou acesso a
windowdurante a renderização no servidor.
O Que É o SSR do Preact e Por Que Ele Importa?
Com SSR, sua árvore de componentes é renderizada para uma string HTML no servidor antes que o navegador receba qualquer coisa. O usuário vê conteúdo imediatamente. O JavaScript carrega em segundo plano e adiciona interatividade posteriormente.
Os benefícios práticos são reais:
- Tempos de carregamento percebidos mais rápidos — conteúdo visível chega já na resposta HTTP inicial.
- Melhor SEO — crawlers leem HTML totalmente formado sem executar JavaScript.
- Resiliência — páginas continuam legíveis mesmo se o JS no cliente falhar ou estiver lento.
O Preact é particularmente adequado para SSR porque seu pequeno runtime adiciona overhead mínimo.
A Ferramenta Central: preact-render-to-string
O SSR do Preact depende do preact-render-to-string, um pacote separado que gerencia a renderização no servidor.
npm install preact-render-to-string
Renderização Síncrona
Para componentes sem dependências assíncronas, renderToString converte sua árvore de componentes em HTML em uma única passagem:
import { renderToString } from 'preact-render-to-string';
const App = () => <h1>Hello from the server</h1>;
const html = renderToString(<App />);
// → <h1>Hello from the server</h1>
Renderização Assíncrona
Quando os componentes buscam dados ou usam Suspense com chunks carregados de forma lazy, use renderToStringAsync em vez disso. Ele aguarda promises e trabalho de renderização assíncrona serem concluídos antes de retornar a string HTML final.
import { renderToStringAsync } from 'preact-render-to-string';
const html = await renderToStringAsync(<App />);
Streaming
Para páginas maiores, as APIs de streaming permitem enviar HTML ao navegador em pedaços conforme cada seção é renderizada. renderToPipeableStream é direcionado para streams do Node.js, enquanto renderToReadableStream é direcionado para ambientes que utilizam a Web Streams API, incluindo plataformas como Cloudflare Workers, Deno e Bun. O streaming melhora o Time to First Byte (TTFB) sem esperar que a renderização completa termine.
Hidratação no Preact: Conectando HTML à Interatividade
Enviar HTML estático é apenas metade do trabalho. Para tornar a página interativa, o Preact precisa hidratar o DOM existente — anexando event listeners e estado sem renderizar tudo do zero.
import { hydrate } from 'preact';
import { App } from './app.js';
hydrate(<App />, document.getElementById('root'));
Use hydrate em vez de render quando o DOM já tiver sido produzido pelo servidor. Usar render descartaria o HTML do servidor e o reconstruiria, anulando o propósito.
Incompatibilidades de hidratação ocorrem quando o HTML renderizado no servidor não corresponde ao que o cliente renderizaria. Causas comuns incluem renderizar timestamps, IDs aleatórios ou ler window durante a passagem no servidor. Mantenha a lógica dos componentes no servidor e no cliente consistente para evitá-las.
Discover how at OpenReplay.com.
Preact Vite SSR: A Configuração Moderna
Para novos projetos, um fluxo baseado em Vite é o padrão prático. O guia de SSR do Vite documenta o padrão de build dupla: uma build voltada para o entry point do servidor e outra para o bundle do cliente. O Preact se integra de forma limpa com o @preact/preset-vite, que lida com JSX, aliases e configurações específicas do Preact.
Para equipes que querem um ponto de partida mais estruturado, o preact-iso oferece utilitários leves de roteamento e pré-renderização projetados especificamente para projetos Preact com Vite.
O Que Manter em Mente
O SSR do Preact compartilha base conceitual com o SSR do React, mas não é idêntico em todos os detalhes de implementação. Algumas APIs de SSR específicas do React não têm equivalentes diretos, e o ecossistema em torno do Preact é menor — um tradeoff justo pelos ganhos de tamanho e performance.
O padrão que funciona de forma confiável: busque seus dados antes de renderizar, passe-os como props, renderize para string no servidor e hidrate no cliente. Comece por aí e, em seguida, adicione streaming ou padrões de renderização mais avançados quando tiver uma razão para isso.
Conclusão
O SSR do Preact oferece um caminho leve e focado em performance para aplicações renderizadas no servidor, sem o overhead de um framework maior. Combinando preact-render-to-string para a passagem no servidor, hydrate para a ativação no cliente e Vite para o pipeline de build, você obtém uma configuração rápida de entregar e fácil de entender. Comece com o fluxo básico de render-e-hidratar, mantenha as saídas do servidor e do cliente alinhadas e recorra ao streaming apenas quando a escala da sua aplicação justificar.
Perguntas Frequentes
Escolha o SSR do Preact quando o tamanho do bundle, o desempenho de cold-start ou o deploy em edge importem mais do que o acesso ao ecossistema mais amplo do React. O pequeno runtime do Preact é ideal para sites com muito conteúdo, páginas de marketing e deploys baseados em workers. Permaneça com o SSR do React se você depende de bibliotecas específicas do React ou precisa de APIs como React Server Components, que o Preact não replica.
Garanta que o servidor e o cliente renderizem a mesma saída para as mesmas props. Evite valores não determinísticos durante a renderização inicial, como Date.now, Math.random ou globais exclusivos do navegador como window e localStorage. Se você precisar de conteúdo exclusivo do cliente, renderize um placeholder estável no servidor e atualize-o dentro de um effect após a conclusão da hidratação.
Muitas bibliotecas do React funcionam através do alias preact/compat, que mapeia imports do React para equivalentes do Preact. Entretanto, bibliotecas que dependem de recursos de SSR específicos do React, como React Server Components ou internals de renderização, podem não se comportar corretamente. Teste cada dependência em seu pipeline de SSR antes de adotá-la.
Provavelmente não. O streaming compensa quando as páginas são grandes, possuem muitos dados ou têm seções que são resolvidas em velocidades diferentes. Para um site pequeno típico, renderToString ou renderToStringAsync produzem resultados rapidamente o suficiente para que o streaming adicione complexidade sem benefício mensurável. Comece com as APIs síncronas ou assíncronas mais simples e adote streaming apenas quando o TTFB se tornar um gargalo real.
Gain Debugging Superpowers
Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.