Publicado em 6 de fevereiro de 2019, atualizado pela última vez em 5 de janeiro de 2026
Uma das principais decisões que os desenvolvedores da Web precisam tomar é onde implementar a lógica e a renderização no aplicativo. Isso pode ser difícil porque há muitas maneiras de criar um site.
Nosso entendimento desse espaço é informado pelo nosso trabalho no Chrome, conversando com grandes sites nos últimos anos. De modo geral, incentivamos os desenvolvedores a considerar a renderização do lado do servidor ou a renderização estática em vez de uma abordagem de reidratação completa.
Para entender melhor as arquiteturas que escolhemos ao tomar esta decisão, precisamos de uma terminologia consistente e de uma estrutura compartilhada para cada abordagem. Em seguida, você pode avaliar melhor as compensações de cada abordagem de renderização do ponto de vista da performance da página.
Terminologia
Primeiro, definimos alguns termos que vamos usar.
Renderização
- Renderização do lado do servidor (SSR, na sigla em inglês)
- Renderizar um app no servidor para enviar HTML, em vez de JavaScript, ao cliente.
- Renderização do lado do cliente (CSR, na sigla em inglês)
- Renderizar um app em um navegador, usando JavaScript para modificar o DOM.
- Pré-renderização
- Executar um aplicativo do lado do cliente no momento da criação para capturar o estado inicial como HTML estático. A "pré-renderização" nesse sentido é diferente da pré-renderização do navegador de navegações futuras.
- Hidratação
- Executar scripts do lado do cliente para adicionar estado e interatividade do aplicativo ao HTML renderizado pelo servidor. A hidratação pressupõe que o DOM não muda.
- Reidratação
- Embora seja usado com frequência para significar a mesma coisa que hidratação, a reidratação implica atualizar regularmente o DOM com o estado mais recente, inclusive após a hidratação inicial
Desempenho
- Time to First Byte (TTFB)
- O tempo entre clicar em um link e o primeiro byte de conteúdo carregando na nova página.
- First Contentful Paint (FCP)
- O tempo em que o conteúdo solicitado (corpo do artigo etc.) fica visível.
- Interaction to Next Paint (INP)
- Uma métrica representativa que avalia se uma página responde de maneira consistente e rápida às entradas do usuário.
- Tempo total de bloqueio (TBT, na sigla em inglês)
- Uma métrica de proxy para INP que calcula quanto tempo a linha de execução principal foi bloqueada durante o carregamento da página.
Renderização do lado do servidor
A renderização do lado do servidor gera o HTML completo de uma página no servidor em resposta à navegação. Isso evita viagens de ida e volta adicionais para buscar dados e criar modelos no cliente, porque o renderizador os processa antes que o navegador receba uma resposta.
A renderização do lado do servidor geralmente produz um FCP rápido. A execução da lógica e da renderização da página no servidor permite evitar o envio de muito JavaScript ao cliente. Isso ajuda a reduzir o TTBT de uma página, o que também pode levar a um INP menor, porque a linha de execução principal não é bloqueada com tanta frequência durante o carregamento da página. Quando a linha de execução principal é bloqueada com menos frequência, as interações do usuário têm mais oportunidades de serem executadas mais cedo.
Isso faz sentido, porque, com a renderização do lado do servidor, você está apenas enviando texto e links para o navegador do usuário. Essa abordagem pode funcionar bem para várias condições de dispositivo e rede e abre otimizações interessantes do navegador, como a análise de documentos de streaming.
Com a renderização do lado do servidor, é menos provável que os usuários fiquem esperando por JavaScript vinculado à CPU para executar antes que possam usar seu site. Mesmo quando não é possível evitar JavaScript de terceiros, o uso da renderização do lado do servidor para reduzir os custos do seu próprio JavaScript primário pode oferecer mais orçamento para o restante. No entanto, há uma possível compensação com essa abordagem: a geração de páginas no servidor leva tempo, o que pode aumentar o TTFB da página.
Se a renderização do lado do servidor é suficiente para seu aplicativo, depende muito de que tipo de experiência você está criando. Há um debate antigo sobre as aplicações corretas da renderização do lado do servidor em comparação com a renderização do lado do cliente, mas você sempre pode optar por usar a renderização do lado do servidor para algumas páginas e não para outras. Alguns sites adotaram técnicas de renderização híbrida com sucesso. Por exemplo, Netflix renderiza no servidor as páginas de destino relativamente estáticas, enquanto prefetching o JavaScript para páginas com muitas interações, oferecendo a essas páginas renderizadas pelo cliente mais pesadas uma chance melhor de carregar rapidamente.
Com muitos frameworks, bibliotecas e arquiteturas modernos, é possível renderizar o mesmo aplicativo no cliente e no servidor. Você pode usar essas técnicas para renderização do lado do servidor. No entanto, as arquiteturas em que a renderização acontece no servidor e no cliente são uma classe de solução própria com características de performance e compensações muito diferentes. Os usuários do React podem usar APIs do DOM do servidor ou soluções criadas nelas, como o Next.js, para renderização do lado do servidor. Os usuários do Vue podem usar o guia de renderização do lado do servidor do Vue ou o Nuxt. O Angular tem o Universal.
No entanto, a maioria das soluções mais populares usa alguma forma de hidratação. Portanto, esteja ciente das abordagens usadas pela sua ferramenta.
Renderização estática
A renderização estática acontece no momento da criação. Essa abordagem oferece um FCP rápido e também um TBT e INP mais baixos, desde que você limite a quantidade de JavaScript do lado do cliente nas suas páginas. Ao contrário da renderização do lado do servidor, ela também alcança um TTFB consistentemente rápido, porque o HTML de uma página não precisa ser gerado dinamicamente no servidor. Geralmente, a renderização estática significa produzir um arquivo HTML separado para cada URL com antecedência. Com as respostas HTML geradas com antecedência, é possível implantar renderizações estáticas em várias CDNs para aproveitar o armazenamento em cache de borda.
As soluções para renderização estática vêm em todos os formatos e tamanhos. Ferramentas como Gatsby são projetadas para fazer com que os desenvolvedores sintam que o aplicativo está sendo renderizado dinamicamente, não gerado como uma etapa de build. Ferramentas de geração de sites estáticos, como 11ty, Jekyll, e Metalsmith adotam a natureza estática, oferecendo uma abordagem mais orientada a modelos.
Uma das desvantagens da renderização estática é que ela precisa gerar arquivos HTML individuais para cada URL possível. Isso pode ser desafiador ou até mesmo inviável quando você precisa prever esses URLs com antecedência e para sites com um grande número de páginas exclusivas.
Os usuários do React podem estar familiarizados com o Gatsby, a exportação estática do Next.js, ou o Navi, que facilitam a criação de páginas a partir de componentes. No entanto, a renderização estática e a pré-renderização se comportam de maneira diferente: as páginas renderizadas estaticamente são interativas sem precisar executar muito JavaScript do lado do cliente, enquanto a pré-renderização melhora o FCP de um aplicativo de página única que precisa ser inicializado no cliente para tornar as páginas verdadeiramente interativas.
Se você não tiver certeza se uma determinada solução é renderização estática ou pré-renderização, desative o JavaScript e carregue a página que você quer testar. Para páginas renderizadas estaticamente, a maioria dos recursos interativos ainda existe sem JavaScript. As páginas pré-renderizadas ainda podem ter alguns recursos básicos, como links com JavaScript desativado, mas a maior parte da página é inerte.
Outro teste útil é usar a limitação de rede no Chrome DevTools e conferir quanto JavaScript é baixado antes que uma página se torne interativa. A pré-renderização geralmente precisa de mais JavaScript para se tornar interativa, e esse JavaScript tende a ser mais complexo do que a abordagem de melhoria progressiva usada na renderização estática.
Renderização do lado do servidor versus renderização estática
A renderização do lado do servidor não é a melhor solução para tudo, porque a natureza dinâmica dela pode ter custos significativos de sobrecarga de computação. Muitas soluções de renderização do lado do servidor
não liberam cedo, atrasam o TTFB ou dobram os dados enviados
(por exemplo, estados embutidos usados pelo JavaScript no cliente). No React,
renderToString() pode ser lento porque é síncrono e de linha de execução única.
As APIs do DOM do servidor React mais recentes
oferecem suporte a streaming, que pode enviar a parte inicial de uma resposta HTML ao
navegador mais cedo enquanto o restante ainda está sendo gerado no servidor.
Para que a renderização do lado do servidor seja "correta", é necessário encontrar ou criar uma solução para o armazenamento em cache de componentes, gerenciar o consumo de memória, usar técnicas de memorização, e outras preocupações. Muitas vezes, você processa ou recria o mesmo app duas vezes, uma no cliente e outra no servidor. A renderização do lado do servidor que mostra o conteúdo mais cedo não necessariamente reduz o trabalho. Se você tiver muito trabalho no cliente depois que uma resposta HTML gerada pelo servidor chegar ao cliente, isso ainda poderá levar a um TBT e INP mais altos para seu site.
A renderização do lado do servidor produz HTML sob demanda para cada URL, mas pode ser mais lenta do que apenas veicular conteúdo renderizado estático. Se você puder fazer o trabalho extra, a renderização do lado do servidor e o armazenamento em cache de HTML podem reduzir significativamente o tempo de renderização do servidor. A vantagem da renderização do lado do servidor é a capacidade de extrair mais dados "ao vivo" e responder a um conjunto mais completo de solicitações do que é possível com a renderização estática. As páginas que precisam de personalização são um exemplo concreto do tipo de solicitação que não funciona bem com a renderização estática.
A renderização do lado do servidor também pode apresentar decisões interessantes ao criar um PWA. É melhor usar o armazenamento em cache do service worker de página inteira ou renderizar no servidor partes individuais do conteúdo?
Renderização do lado do cliente
A renderização do lado do cliente significa renderizar páginas diretamente no navegador com JavaScript. Toda a lógica, busca de dados, criação de modelos e roteamento são processados no cliente, e não no servidor. O resultado eficaz é que mais dados são transmitidos do servidor para o dispositivo do usuário, e isso tem seu próprio conjunto de compensações.
A renderização do lado do cliente pode ser difícil de fazer e manter rápida para dispositivos móveis.
Com um pouco de trabalho para manter um orçamento de JavaScript apertado
e oferecer valor no menor número possível de viagens de ida e volta, é possível fazer com que a renderização do lado do cliente quase replique
a performance da renderização pura do lado do servidor. É possível fazer com que o analisador funcione
mais rápido entregando scripts e dados críticos usando <link rel=preload>
Também recomendamos considerar o uso de padrões como o PRPL
para garantir que as navegações iniciais e subsequentes sejam instantâneas.
A principal desvantagem da renderização do lado do cliente é que a quantidade de JavaScript necessária tende a aumentar à medida que um aplicativo cresce, o que pode afetar o INP de uma página. Isso se torna especialmente difícil com a adição de novas bibliotecas JavaScript, polyfills e código de terceiros, que competem pelo poder de processamento e geralmente precisam ser processados antes que o conteúdo de uma página possa ser renderizado.
As experiências que usam a renderização do lado do cliente e dependem de grandes pacotes JavaScript precisam considerar a divisão agressiva de código para reduzir o TBT e o INP durante o carregamento da página, bem como o carregamento lento do JavaScript para veicular apenas o que o usuário precisa, quando necessário. Para experiências com pouca ou nenhuma interatividade, a renderização do lado do servidor pode representar uma solução mais escalonável para esses problemas.
Para quem cria aplicativos de página única, identificar as partes principais da interface do usuário
compartilhadas pela maioria das páginas permite aplicar a
técnica de armazenamento em cache do shell do aplicativo. Combinado com service workers, isso pode melhorar muito a
performance percebida em visitas repetidas, porque a página pode carregar o
HTML e as dependências do shell do aplicativo de CacheStorage muito rapidamente.
A reidratação combina a renderização do lado do servidor e do cliente
A hidratação é uma abordagem que atenua as compensações entre a renderização do lado do cliente e do servidor , fazendo as duas. As solicitações de navegação, como carregamentos ou recarregamentos de página inteira, são processadas por um servidor que renderiza o aplicativo em HTML. Em seguida, o JavaScript e os dados usados para renderização são incorporados ao documento resultante. Quando feito com cuidado, isso alcança um FCP rápido, como a renderização do lado do servidor, e depois "retoma" a renderização novamente no cliente.
Essa é uma solução eficaz, mas pode ter desvantagens consideráveis de performance
A principal desvantagem da renderização do lado do servidor com reidratação é que ela pode ter um impacto negativo significativo no TBT e no INP, mesmo que melhore o FCP. As páginas renderizadas pelo servidor podem parecer carregadas e interativas, mas não podem responder à entrada até que os scripts do lado do cliente para componentes sejam executados e os gerenciadores de eventos tenham sido anexados. Em dispositivos móveis, isso pode levar minutos, confundindo e frustrando o usuário.
Um problema de reidratação: um app pelo preço de dois
Para que o JavaScript do lado do cliente assuma com precisão de onde o servidor parou, sem solicitar novamente todos os dados com que o servidor renderizou o HTML, a maioria das soluções de renderização do lado do servidor serializa a resposta das dependências de dados de uma interface como tags de script no documento. Como isso duplica muito HTML, a reidratação pode causar mais problemas do que apenas interatividade atrasada.
O servidor está retornando uma descrição da interface do aplicativo em resposta a uma
solicitação de navegação, mas também está retornando os dados de origem usados para compor essa
interface e uma cópia completa da implementação da interface, que é inicializada no
cliente. A interface não se torna interativa até que bundle.js termine de
carregar e executar.
As métricas de performance coletadas de sites reais usando renderização do lado do servidor e reidratação indicam que raramente é a melhor opção. O motivo mais importante é o efeito na experiência do usuário, quando uma página parece pronta, mas nenhum dos recursos interativos funciona.
Há esperança para a renderização do lado do servidor com reidratação. No curto prazo, usar apenas a renderização do lado do servidor para conteúdo altamente armazenável em cache pode reduzir o TTFB, produzindo resultados semelhantes à pré-renderização. A reidratação incremental, progressiva ou parcial pode ser a chave para tornar essa técnica mais viável no futuro.
Transmitir a renderização do lado do servidor e reidratar progressivamente
A renderização do lado do servidor teve vários desenvolvimentos nos últimos anos.
A renderização do lado do servidor de streaming
permite enviar HTML em blocos que o navegador pode renderizar progressivamente à medida que é
recebido. Isso pode levar a marcação aos usuários mais rapidamente, acelerando o FCP. No
React, os streams serem assíncronos em renderToPipeableStream(), em comparação com
síncrono renderToString(), significa que a contrapressão é bem processada.
A reidratação progressiva também vale a pena considerar (o React a implementou). Com esta abordagem, partes individuais de um aplicativo renderizado pelo servidor são "inicializadas" ao longo do tempo, em vez da abordagem comum atual de inicializar todo o aplicativo de uma só vez. Isso pode ajudar a reduzir a quantidade de JavaScript necessária para tornar as páginas interativas, porque permite adiar o upgrade do lado do cliente de partes de baixa prioridade da página para evitar que ela bloqueie a linha de execução principal, permitindo que as interações do usuário aconteçam mais cedo depois que o usuário as inicia.
A reidratação progressiva também pode ajudar a evitar um dos problemas mais comuns
de reidratação da renderização do lado do servidor: uma árvore DOM renderizada pelo servidor é
destruída e reconstruída imediatamente, geralmente porque a renderização síncrona inicial
do lado do cliente exigia dados que não estavam totalmente prontos, geralmente uma
Promise que ainda não foi resolvida.
Reidratação parcial
A reidratação parcial tem se mostrado difícil de implementar. Essa abordagem é uma extensão da reidratação progressiva que analisa partes individuais da página (componentes, visualizações ou árvores) e identifica as partes com pouca interatividade ou sem reatividade. Para cada uma dessas partes quase estáticas, o código JavaScript correspondente é transformado em referências inertes e recursos decorativos, reduzindo a pegada do lado do cliente para quase zero.
A abordagem de reidratação parcial vem com seus próprios problemas e concessões. Ela apresenta alguns desafios interessantes para o armazenamento em cache, e a navegação do lado do cliente significa que não podemos presumir que o HTML renderizado pelo servidor para partes inertes do aplicativo esteja disponível sem um carregamento de página inteira.
Renderização trisomórfica
Se os service workers forem uma opção para você, considere a renderização trisomórfica. Essa técnica permite usar a renderização do lado do servidor de streaming para navegações iniciais ou não JavaScript e, em seguida, fazer com que o service worker assuma a renderização de HTML para navegações após a instalação. Isso pode manter os componentes e modelos armazenados em cache atualizados e ativar navegações no estilo SPA para renderizar novas visualizações na mesma sessão. Essa abordagem funciona melhor quando é possível compartilhar o mesmo código de modelo e roteamento entre o servidor, a página do cliente e o service worker.
Considerações de SEO
Ao escolher uma estratégia de renderização da Web, as equipes geralmente consideram o impacto do SEO. A renderização do lado do servidor é uma escolha popular para oferecer uma experiência "completa" que os rastreadores possam interpretar. Os rastreadores podem entender JavaScript, mas geralmente há limitações na forma como eles renderizam. A renderização do lado do cliente pode funcionar, mas geralmente precisa de mais testes e sobrecarga. Mais recentemente, a renderização dinâmica também se tornou uma opção que vale a pena considerar se sua arquitetura depende muito do JavaScript do lado do cliente.
Conclusão
Ao decidir sobre uma abordagem de renderização, meça e entenda quais são seus gargalos. Considere se a renderização estática ou do lado do servidor pode levar você até a maior parte do caminho. Não há problema em enviar principalmente HTML com JavaScript mínimo para tornar uma experiência interativa. Confira um infográfico útil que mostra o espectro cliente-servidor:
Créditos
Agradecemos a todos pelas análises e inspiração:
Jeffrey Posnick, Houssein Djirdeh, Shubhie Panicker, Chris Harrelson e Sebastian Markbåge.