CategoriaCódigo e arquitetura
Renderização no Next.js: estático, incremental ou dinâmico
No Next.js, a escolha entre renderização estática, incremental e dinâmica é uma decisão sobre por quanto tempo o dado pode envelhecer. O estático renderiza uma vez no build. O incremental renderiza no build e reconstrói em segundo plano depois de uma janela. O dinâmico renderiza a cada requisição. A maioria dos projetos escolhe o dinâmico por padrão e paga por isso.
O que cada modo faz no servidor
Renderização decide quando o HTML é produzido. O Next.js torna a prerenderização o padrão para qualquer componente que não use uma API de tempo de requisição, segundo o glossário do framework (em inglês).
- Estático. O build produz o HTML e o payload de Server Components, e a CDN serve aquele arquivo. O servidor não faz trabalho quando o visitante chega.
- Incremental. O build prerenderiza a página, e a primeira requisição depois da janela de revalidação ainda recebe a cópia antiga enquanto uma versão nova é gerada em segundo plano. O guia de ISR (em inglês) documenta essa sequência, da primeira resposta antiga até a atualização em cache.
- Dinâmico. O servidor renderiza a página para aquela requisição. Componentes que leem
cookies,headers,searchParamsouparamsde rota entram nesse modo, como afirma o guia de cache (em inglês).
O que o visitante baixa
O visitante sempre baixa HTML. O que muda é de onde o HTML vem e quanto JavaScript chega junto.
Uma página estática chega de uma máquina perto de quem lê, então a resposta não espera por um banco de dados. Uma página dinâmica chega depois que o servidor terminou o trabalho, então a resposta carrega a latência da dependência mais lenta daquela página.
O React afirma que Server Components renderizam antes do empacotamento, em um ambiente separado do app cliente. No exemplo da própria documentação, as bibliotecas usadas para renderizar markdown nem entram no bundle. O cliente recebe a saída já renderizada.
Isso não quer dizer que página estática não baixe JavaScript. Client Components ainda enviam um bundle e ainda hidratam no navegador, e hidratação é trabalho na thread principal. A referência de hidratação do React descreve o cliente assumindo o HTML do servidor e ligando os manipuladores de evento nele.
Cache não é renderização
Na conversa, as duas coisas costumam se misturar, e é daí que vem quase toda a confusão.
Renderização responde quando o HTML é produzido. Cache responde se um resultado produzido é guardado e reaproveitado. O guia de cache do Next.js (em inglês) define cache como guardar o resultado da busca de dados e de outras computações para servir requisições futuras mais rápido, sem refazer o trabalho.
Ou seja, uma coisa não depende da outra.
- Uma página dinâmica pode ler de uma fonte de dados com cache, então ela renderiza a cada requisição sem bater no banco a cada requisição.
- Uma página estática pode ser re-renderizada no build e ainda assim não ser guardada, se a camada de entrega receber a ordem de não armazenar.
- O cliente mantém um cache próprio de navegação, separado dos dois.
Desde o Next.js 16, o modelo recomendado é o Cache Components (em inglês), e apps novos criados com create-next-app já vêm com ele ligado. A diretiva use cache guarda uma função de dados ou um componente inteiro, cada um com o próprio prazo de validade. A página sobre a filosofia de renderização (em inglês) tira a consequência: a fronteira entre estático e dinâmico agora fica no componente, não na rota. Uma página pode entregar uma casca estática e transmitir as partes de tempo de requisição atrás de um limite de Suspense. Projetos que ficaram no modelo anterior (em inglês) ainda configuram cache por segmento de rota, então confira qual modelo o código usa antes de ler a configuração.
Onde os modos aparecem no Core Web Vitals
A régua é a do Core Web Vitals: carregamento principal em 2,5 segundos, resposta à interação em 200 milissegundos e deslocamento de layout de 0,1 no máximo, lidos no percentil 75. O post sobre framework ou site estático explica cada métrica.
Renderização estática move o trabalho para o build, então a resposta não espera por uma consulta. Isso ajuda o LCP, porque o maior elemento pode chegar cedo. A mesma página ainda roda hidratação, e a hidratação disputa a thread principal, que é onde o INP se decide.
Renderização dinâmica move o trabalho para o tempo da requisição. O artigo de Web Vitals do Google cita tempo de resposta lento do servidor como causa de diagnóstico por trás de um LCP ruim. Uma página que consulta três serviços antes de renderizar herda o mais lento dos três em cada visita.
Nenhum dos dois modos decide o CLS. Estabilidade de layout depende de o esqueleto reservar espaço para o que chega depois, incluindo conteúdo que entra por streaming em uma fronteira de Suspense.
O que o Nielsen Norman Group diz sobre a espera
O framework decide quando o HTML está pronto. Quem lê percebe só a espera, e o Nielsen Norman Group mede esse lado há décadas.
Os limites de tempo de resposta são o material mais antigo e mais citado. Response Times: The 3 Important Limits (em inglês) coloca 0,1 segundo como o ponto em que o sistema parece instantâneo e 1,0 segundo como o limite para um fluxo de raciocínio sem interrupção. Os 10 segundos aparecem como o limite para manter a atenção.
Website Response Times (em inglês) atualiza esse enquadramento para a web. Ele afirma que os usuários precisam de resposta em menos de 0,1 segundo para manipulação direta, e que um atraso de 10 segundos faz a pessoa trocar de tarefa.
Progress Indicators Make a Slow System Less Insufferable (em inglês) acrescenta o caso em que a espera é inevitável. O artigo afirma que um resultado que passa de 10 segundos deve vir com estimativa, porque os usuários abandonam a tarefa em vez de esperar.
Skeleton Screens 101 (em inglês) fecha a ligação com este post. Ele recomenda a tela de esqueleto para um carregamento de página inteira entre 2 e 10 segundos, que é exatamente a janela em que cai uma rota dinâmica sem cache.
Os quatro artigos não contam uma história só sobre os mesmos 10 segundos. O artigo de tempo de resposta trata o atraso longo como falha a evitar, e o de indicadores de progresso trata como caso a projetar com estimativa. O de esqueleto fica no meio, aceita a espera e exige que o layout reserve o espaço (NN/g, tempos de resposta (em inglês), NN/g, indicadores de progresso (em inglês), NN/g, skeleton screens (em inglês)).
Quando o dinâmico é a resposta correta
Quando o dado muda para cada visitante, renderização dinâmica não é erro. É o que o caso pede.
- Qualquer coisa lida de sessão, cookie ou cabeçalho de autorização. O Next.js lista esses itens como APIs de tempo de requisição (em inglês), que precisam de informação disponível só no momento da requisição.
- Preço, estoque e disponibilidade que mudam no mesmo minuto.
- Painéis autenticados e qualquer tela montada a partir dos registros de quem lê.
- Conteúdo em que uma resposta velha está errada, e não só desatualizada, como status de pagamento ou aviso legal.
A documentação do Next.js (em inglês) é explícita nesse ponto. Para componentes que precisam de dado fresco a cada requisição, ela diz para não usar cache e para transmitir esses componentes atrás de uma fronteira de Suspense.
O custo escondido de escolher dinâmico por padrão
O custo é pago a cada visita e quase nunca aparece separado na fatura.
- Cada requisição roda a renderização de novo. A dependência mais lenta da página define o piso da resposta.
- A rede de borda fica quase ociosa. Um arquivo estático absorve um pico de tráfego, e uma renderização por requisição não absorve.
- A computação é cobrada por requisição, então uma página que muda uma vez por dia é paga milhares de vezes.
- O time adiciona cache de volta depois, camada por camada, e reconstrói com mais peças o comportamento que tinha no build.
Nada disso é desperdício quando o dado é mesmo por usuário. O desperdício aparece quando ninguém nomeou a janela em que o dado pode envelhecer, e o dinâmico foi o caminho de menor resistência.
Como tomar a decisão
Diga, em segundos, quanto tempo o dado pode ficar desatualizado, e o modo de renderização sai daí.
- Zero segundo, ou uma resposta diferente por visitante. Dinâmico.
- Uma janela medida em horas ou dias. Prerenderize no build e revalide.
- Desconhecido. Comece estático e meça. Mover uma rota para dinâmico depois é mudança de configuração, não reescrita.
O padrão do framework ajuda nessa hora. No Next.js, uma página que nunca toca em API de tempo de requisição já sai prerenderizada, e esse é o padrão declarado na documentação (em inglês).
Modo de renderização é uma afirmação sobre o dado, não sobre o framework. Escolha quanto tempo o dado aguenta sem atualizar, e o modo deixa de ser gosto e vira consequência.
Fontes
- Next.js, Glossário (em inglês)
- Next.js, Caching (em inglês)
- Next.js, Rendering Philosophy (em inglês)
- Next.js, Caching (Previous Model) (em inglês)
- Next.js, Incremental Static Regeneration (em inglês)
- React, Server Components
- React, hydrateRoot
- Google, Web Vitals
- Nielsen Norman Group, Response Times: The 3 Important Limits (em inglês)
- Nielsen Norman Group, Website Response Times (em inglês)
- Nielsen Norman Group, Progress Indicators Make a Slow System Less Insufferable (em inglês)
- Nielsen Norman Group, Skeleton Screens 101 (em inglês)


