Next.js
React
Server Components
Arquitetura
Desenvolvimento Web

Next.js App Router: o Guia para Pensar em Servidor por Padrão

O App Router inverte a regra: servidor por padrão, cliente por exceção. Veja o que isso muda no seu time.

Quando o Next.js lançou o App Router, ele fez algo que parece técnico mas é, no fundo, uma decisão de mentalidade: inverteu o padrão. Antes, todo componente era de cliente até você dizer o contrário. Agora, todo componente é de servidor até você marcar que precisa ser de cliente.

Essa inversão é pequena na sintaxe e enorme na prática. Ela muda a pergunta que o time faz a cada componente. Em vez de assumir que tudo roda no navegador, você passa a justificar por que algo precisaria rodar lá.

Para quem vem do React tradicional, o App Router não é só uma pasta nova com um roteador diferente. É um convite a repensar onde cada pedaço da aplicação deveria viver. E esse convite costuma desorientar antes de fazer sentido.

O padrão se inverteu

No App Router, layouts e pages são componentes de servidor por padrão. Isso significa que, ao criar uma página nova, ela já nasce rodando no servidor, sem você fazer nada. O código dela não vai para o navegador, e a busca de dados pode acontecer ali mesmo, antes da resposta sair.

A consequência imediata é que muita coisa que você empurraria para o cliente agora fica naturalmente no servidor. A lista de produtos, o conteúdo do artigo, o cabeçalho com dados do usuário, tudo isso é renderizado antes de chegar, sem custo de JavaScript no aparelho.

Quando você precisa de interatividade, marca o componente com a diretiva "use client". A partir desse ponto, aquele componente e o que ele renderiza passam a rodar no navegador, com estado e eventos. É uma fronteira explícita, não um acidente.

O efeito colateral saudável é que o cliente vira exceção consciente. Você não cai nele por inércia, você escolhe quando entrar. Se isso ainda soa abstrato, vale revisar o que são React Server Components antes de seguir.

Quando o componente deve ser de servidor

A pergunta certa é sobre a natureza do trabalho. Se o componente apenas busca e exibe informação, ele tem tudo para ser de servidor. Páginas de listagem, conteúdo de blog, detalhes de um pedido, dashboards que só mostram números: nada disso precisa do navegador para existir.

Componentes de servidor brilham na busca de dados. Você consulta o banco direto, chama serviços internos com a latência baixa de quem está dentro da infraestrutura e monta o resultado pronto. Não precisa de uma rota de API intermediária só para o navegador conseguir pedir o dado, porque o componente já está do lado certo.

Há também o ganho de manter peso fora do cliente. Bibliotecas pesadas de formatação, processamento de markdown, manipulação de datas: se isso roda no servidor, nunca entra no pacote que o usuário baixa. O bundle encolhe, e o aparelho do usuário agradece.

A regra mental que funciona é esta: comece assumindo servidor. Só mova para o cliente quando bater uma necessidade concreta de interação. Resistir ao impulso de marcar tudo como cliente é metade da batalha.

Quando o componente precisa ser de cliente

Nem tudo cabe no servidor, e tentar forçar isso gera frustração. Há um conjunto claro de situações que exigem cliente, e reconhecê-las rápido evita perda de tempo.

A primeira é estado que muda na tela. Um contador, uma aba selecionada, um menu que abre e fecha: qualquer coisa que precise lembrar de algo entre interações vive no cliente. A segunda é evento do usuário. Clique, digitação, arrastar, qualquer manipulação direta acontece no navegador, porque é lá que o usuário está.

A terceira é o uso de recursos do navegador. Acesso ao armazenamento local, geolocalização, leitura de tamanho da janela, qualquer coisa que só existe no ambiente do navegador obriga o componente a ser de cliente. Não há como executar isso no servidor, simplesmente porque o servidor não tem janela nem mouse.

O detalhe que destrava a cabeça do time é entender que isso não é tudo ou nada. Você pode ter uma página de servidor que renderiza um pequeno componente de cliente apenas para o botão interativo. O resto da página continua leve e renderizado no servidor. A interatividade fica isolada onde ela realmente importa, em vez de contaminar a página inteira.

A busca de dados muda de lugar

No modelo antigo, buscar dados era um ritual conhecido: o componente montava, disparava um efeito, chamava uma API, lidava com estados de carregamento e erro, e atualizava o estado quando a resposta voltava. Funcionava, mas era verboso e cheio de armadilhas.

Com componentes de servidor, a busca de dados volta a ser direta. Você busca o dado durante a renderização no servidor, espera o resultado ali mesmo e devolve a interface pronta. Some boa parte da dança de estados de carregamento no cliente, porque o dado já chega junto com a página.

Isso simplifica o código e melhora a experiência ao mesmo tempo, o que é raro. O usuário recebe conteúdo já preenchido, sem aquela sequência de telas vazias piscando enquanto cada parte carrega. E quando você precisa de carregamento progressivo, o framework oferece streaming para entregar pedaços conforme ficam prontos, assunto que vale aprofundar em cache e streaming no Next.js.

A mutação de dados segue lógica parecida. Em vez de montar uma API completa para cada formulário, você pode usar Server Actions, funções que rodam no servidor e são chamadas direto da interface. Isso fecha o ciclo: leitura e escrita perto da fonte, sem camadas que existiam só para servir o navegador.

A mudança de mentalidade que o time enfrenta

A parte difícil do App Router não é a sintaxe. É desaprender o reflexo de que tudo roda no navegador. Times experientes em React tendem a marcar componentes como cliente por hábito, porque foi assim que aprenderam, e aí perdem boa parte do ganho.

O sintoma clássico é o "use client" no topo de quase todo arquivo. Quando isso acontece, a aplicação volta a ser uma SPA disfarçada, com o peso de antes e a complexidade nova por cima. O time precisa internalizar que cada marcação de cliente é uma decisão a justificar, não um padrão a copiar.

Há também um ajuste mental sobre onde o código executa. Pensar que parte da árvore roda no servidor e parte no navegador exige cuidado com o que cada lado pode fazer. Tentar usar um recurso de navegador em componente de servidor gera erro, e esses tropeços iniciais são parte normal do aprendizado.

Depois que a ficha cai, o modelo fica intuitivo. A pergunta isso precisa de interação vira automática, e o time passa a desenhar interfaces leves por padrão. Mas chegar lá exige liderança técnica disposta a revisar código e a corrigir o reflexo antigo com paciência.

Se você está avaliando adotar o App Router no seu time, trate a curva de aprendizado como parte do projeto, não como um detalhe. Reserve tempo para o time errar, revisar e ajustar a intuição. Para situar essa escolha dentro de uma decisão de arquitetura maior, siga para o movimento server-first como decisão de arquitetura.

Leia também