O App Router do Next.js mudou fundamentalmente a forma como construímos aplicações React. Com a estabilização completa no Next.js 15, a divisão entre o servidor e o cliente deixou de ser uma barreira para se tornar uma ferramenta de precisão.
Mas como o Next.js realmente envia componentes do servidor para o cliente sem perder o estado? O segredo está no React Server Components Payload (RSC Payload).
O Mito do SSR Tradicional vs RSC
No Server-Side Rendering (SSR) clássico (via getServerSideProps), o servidor gera o HTML completo, envia para o browser, e então o JavaScript é baixado para fazer a "hidratação" (hydration). O problema? O componente que fez o fetch de dados no servidor precisava ter seu JavaScript enviado ao cliente de qualquer maneira.
Com React Server Components (RSC), o código do componente nunca cruza a rede.
Por padrão, todos os componentes no App Router são Server Components. Você só adiciona "use client" naqueles que precisam de interatividade (hooks, onClick, estado).
Anatomia do RSC Payload
Quando você navega no Next.js 15, o browser não baixa HTML puro via AJAX. Ele baixa um formato especial, semelhante a JSON, que o React consegue reconciliar com a árvore do DOM existente sem destruir o estado atual.
Se você observar a aba Network do DevTools, verá uma resposta parecida com isto:
0: ["$","div",null,{"className":"layout","children":["$","nav",null,{...}]}]
1: I{"id":"./src/components/InteractiveButton.tsx","chunks":["app/layout"],"name":""}
Neste payload:
- O React renderizou a
dive anavno servidor e enviou apenas o resultado estrutural. - A referência
Iinstrui o React no cliente: "Aqui existe um Client Component. Baixe este chunk de JavaScript e hidrate-o."
Isso reduz drasticamente o tamanho do bundle JavaScript principal (LCP e TTI agradecem).
Streaming com Suspense: UX Elevada
No Next.js 15, o uso de Suspense em conjunto com a API nativa de fetch ou Server Actions permite que você aplique a técnica de Streaming.
Em vez de bloquear a renderização inteira da página esperando uma query lenta no banco de dados, você entrega a casca da página (shell) instantaneamente.
import { Suspense } from 'react';
import { SkeletonCard } from '@/components/ui/skeleton';
import { SlowDataComponent } from '@/components/slow-data';
export default function Dashboard() {
return (
<section>
<h1>Seu Dashboard</h1>
{/* O Suspense Boundary inicia o Streaming */}
<Suspense fallback={<SkeletonCard />}>
<SlowDataComponent />
</Suspense>
</section>
);
}
Por baixo dos panos, o Next.js mantém a conexão HTTP aberta (usando Transfer-Encoding: chunked). Assim que o SlowDataComponent resolve no servidor, o Next.js ejeta um script inline direto na stream HTML que substitui o <SkeletonCard /> pelo conteúdo real.
Conclusão
Aprender a isolar responsabilidades no App Router — deixando a pesada lógica de dados e dependências no servidor e enviando ao cliente apenas componentes "burros" de UI — é a chave para dominar o Next.js 15. A performance não é mais uma otimização pós-lançamento; ela já vem construída na arquitetura.