Publicado em: 6 de fevereiro de 2019, última atualização: 5 de janeiro de 2026
Uma das principais decisões que os desenvolvedores 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.
Nossa compreensão desse espaço é baseada no nosso trabalho no Chrome, conversando com sites grandes nos últimos anos. De modo geral, recomendamos que os desenvolvedores considerem 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 estamos escolhendo ao tomar essa decisão, precisamos de uma terminologia consistente e de um framework compartilhado para cada abordagem. Em seguida, você poderá avaliar melhor as vantagens e desvantagens de cada abordagem de renderização do ponto de vista do desempenho da página.
Terminologia
Primeiro, vamos definir alguns termos que serão usados.
Renderização
- Renderização do lado do servidor (SSR)
- Renderizar um app no servidor para enviar HTML, em vez de JavaScript, ao cliente.
- Renderização do lado do cliente (CSR)
- 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 de navegações futuras pelo navegador.
- Hidratação
- Executar linguagem de 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 frequentemente usado para significar o mesmo 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 o clique em um link e o carregamento do primeiro byte de conteúdo na nova página.
- First Contentful Paint (FCP)
- O momento 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 forma consistente e rápida às entradas do usuário.
- Total Blocking Time (TBT)
- Uma métrica de proxy para INP que calcula por 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 idas e voltas adicionais para busca de dados e modelagem no cliente, porque o renderizador as processa antes que o navegador receba uma resposta.
A renderização do lado do servidor geralmente produz uma FCP rápida. Executar a lógica da página e a renderização no servidor evita o envio de muitos JavaScripts para o cliente. Isso ajuda a reduzir o TBT 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 de 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 uma variedade de 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 precisem esperar que o JavaScript vinculado à CPU seja executado antes de usar o site. Mesmo quando não é possível evitar o JavaScript de terceiros, usar a renderização do lado do servidor para reduzir os custos de JavaScript próprios pode dar mais orçamento para o restante. No entanto, há uma possível desvantagem nessa abordagem: gerar 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 do tipo de experiência que você está criando. Há um longo debate 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, a Netflix renderiza no servidor as páginas de destino relativamente estáticas, enquanto prefetching o JavaScript para páginas com muita interação, o que dá a essas páginas mais pesadas renderizadas pelo cliente uma chance melhor de carregar rapidamente.
Com muitos frameworks, bibliotecas e arquiteturas modernas, é possível renderizar o mesmo aplicativo no cliente e no servidor. É possível 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 própria de solução com características de desempenho e compensações muito diferentes. Os usuários do React podem usar APIs DOM do servidor ou soluções criadas com base 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, as soluções mais conhecidas usam alguma forma de hidratação. Por isso, fique atento às abordagens usadas pela sua ferramenta.
Renderização estática
A renderização estática ocorre no momento da criação. Essa abordagem oferece um FCP rápido, além de um TBT e um INP menores, desde que você limite a quantidade de JavaScript do lado do cliente nas 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. Em geral, 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 o Gatsby foram projetadas para 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 difícil 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 com base em 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 é de renderização estática ou pré-renderização, desative o JavaScript e carregue a página que 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 o JavaScript desativado, mas a maior parte da página fica inerte.
Outro teste útil é usar a limitação de rede no Chrome DevTools e ver quanto JavaScript é transferido por download 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 aprimoramento progressivo usada na renderização estática.
Renderização do lado do servidor x 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 overhead de computação. Muitas soluções de renderização do lado do servidor não fazem a limpeza antecipada, atrasam o TTFB ou duplicam os dados enviados (por exemplo, estados inline usados pelo JavaScript no cliente). No React,
renderToString() pode ser lento porque é síncrono e de linha de execução única.
As APIs DOM do servidor React mais recentes
oferecem suporte ao streaming, que pode enviar a parte inicial de uma resposta HTML para o
navegador mais rapidamente, enquanto o restante ainda está sendo gerado no servidor.
Para que a renderização do lado do servidor funcione corretamente, pode ser necessário encontrar ou criar uma solução para 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, isso ainda poderá levar a um TBT e um 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 exibir conteúdo renderizado estático. Se você puder fazer o trabalho extra, a renderização do lado do servidor com o armazenamento em cache de HTML pode 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 em página inteira ou renderizar partes individuais de conteúdo no servidor?
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, modelos e roteamento são processados no cliente, e não no servidor. O resultado é que mais dados são transmitidos do servidor para o dispositivo do usuário, o que tem suas próprias vantagens e desvantagens.
A renderização do lado do cliente pode ser difícil de criar e manter rápida para dispositivos móveis.
Com um pouco de trabalho para manter um orçamento de JavaScript restrito
e agregar 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
o desempenho da renderização pura do lado do servidor. Para que o analisador funcione
mais rápido, envie scripts e dados essenciais usando <link rel=preload>.
Também recomendamos o uso de padrões como 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 o aplicativo cresce, o que pode afetar a INP de uma página. Isso se torna especialmente difícil com a adição de novas bibliotecas JavaScript, polyfills e códigos 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 de JavaScript precisam considerar a divisão agressiva de código para reduzir o TBT e o INP durante o carregamento de página, além de carregar o JavaScript de forma lenta 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 drasticamente
a performance percebida em visitas repetidas, porque a página pode carregar o
HTML do shell do aplicativo e as dependências de CacheStorage muito rapidamente.
A reidratação combina a renderização do lado do servidor e do lado do cliente
A hidratação é uma abordagem que reduz as compensações entre a renderização do lado do cliente e do lado do servidor fazendo as duas coisas. 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 feita com cuidado, essa abordagem alcança uma FCP rápida, como a renderização do lado do servidor, e "retoma" o processo renderizando novamente no cliente.
Essa é uma solução eficaz, mas pode ter desvantagens de desempenho consideráveis.
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 no 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 manipuladores de eventos sejam anexados. Em dispositivos móveis, isso pode levar minutos, o que confunde e frustra 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 o controle de onde o servidor parou, sem solicitar novamente todos os dados que o servidor usou para renderizar 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 script no documento. Como isso duplica muito HTML, a reidratação pode causar mais problemas do que apenas atrasar a interatividade.
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 só se torna interativa depois que o bundle.js termina de
carregar e executar.
As métricas de performance coletadas de sites reais que usam renderização do lado do servidor e reidratação indicam que essa 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 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.
Renderização do lado do servidor de streaming e reidratação progressiva
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 são
recebidos. Isso pode fazer com que a marcação chegue mais rápido aos usuários, acelerando a FCP. No
React, os streams são assíncronos em renderToPipeableStream(), em comparação com
renderToString() síncronos, o que significa que a contrapressão é bem processada.
A reidratação progressiva também é uma opção (o React já implementou isso). Com essa 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 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 uma das armadilhas mais comuns
da reidratação de renderização do lado do servidor: uma árvore do DOM renderizada pelo servidor é
destruída e imediatamente recriada, geralmente porque a renderização síncrona
inicial do lado do cliente exigia dados que não estavam prontos, geralmente uma
Promise que ainda não foi resolvida.
Reidratação parcial
A reidratação parcial é 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, o código JavaScript correspondente é transformado em referências inertes e recursos decorativos, reduzindo a pegada do lado do cliente a quase zero.
A abordagem de reidratação parcial tem seus próprios problemas e desvantagens. Isso representa 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 completo.
Renderização trissomó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 que não sejam em JavaScript e, em seguida, fazer com que o service worker assuma a renderização do HTML para navegações depois de instalado. Isso pode manter os componentes e modelos em cache atualizados e permitir 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 sobre 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 comum para oferecer uma experiência de "aparência completa" que os rastreadores podem interpretar. Os rastreadores podem entender o 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 a 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 ajudar você a chegar lá. Não há problema em enviar principalmente HTML com o mínimo de JavaScript para criar uma experiência interativa. Confira um infográfico útil que mostra o espectro servidor-cliente:
Créditos
Agradecemos a todos pelas avaliações e inspiração:
Jeffrey Posnick, Houssein Djirdeh, Shubhie Panicker, Chris Harrelson e Sebastian Markbåge.