React Server Components (RSC) foram anunciados em 2020, ficaram experimentais por anos e finalmente, em 2026, são produção mainstream. Next.js 15 os tornou default, React Router 7 os suporta e até frameworks menores aderiram. A promessa: componentes que rodam no servidor, enviando HTML e dados sem mandar JavaScript pro cliente. A realidade: poderoso, mas exige reaprender React.
RSC não é 'React mais rápido'. É um modelo mental diferente. Server Components não têm estado, não têm efeitos, não acessam o DOM. Tentar usar useState num Server Component é o erro número 1 de quem migra. Entenda a divisão antes de escrever uma linha.
Server vs Client: a divisão fundamental
Por padrão, todo componente em um app RSC é Server Component: roda no servidor, pode buscar dados direto (async/await no componente!), e não envia JS pro cliente. Quando você precisa de interatividade — estado, eventos, hooks de browser — marca o componente com 'use client'. A arte está em manter a fronteira client o menor possível.
// Server Component (padrão) — busca dados direto, zero JS no cliente
async function ProjectList() {
// Sem useEffect, sem useState, sem loading state manual
const res = await fetch("https://api.github.com/users/bernardopg/repos");
const projects = await res.json();
return (
<ul>
{projects.map((p) => (
// LikeButton é a ÚNICA parte que vira JS no cliente
<li key={p.id}>
{p.name}
<LikeButton projectId={p.id} />
</li>
))}
</ul>
);
}
// Client Component — só o que precisa de interatividade
"use client";
import { useState } from "react";
function LikeButton({ projectId }: { projectId: number }) {
const [liked, setLiked] = useState(false);
return (
<button onClick={() => setLiked(!liked)}>
{liked ? "★" : "☆"}
</button>
);
}A regra de ouro: 'use client' marca uma FRONTEIRA, não um arquivo isolado. Tudo importado por um Client Component também vira client. Coloque o 'use client' o mais fundo possível na árvore — nas folhas interativas, não no topo.
O ganho real de performance
O benefício concreto é o bundle de JavaScript. Um app RSC bem feito envia só o JS dos Client Components — frequentemente 30-50% menos que um SPA equivalente. Menos JS = parse mais rápido, Time to Interactive menor, melhor INP. Para conteúdo (blogs, e-commerce, dashboards), o ganho de Core Web Vitals é mensurável.
- Bundle inicial: 30-50% menor (só Client Components vão pro cliente)
- Data fetching: sem waterfalls de useEffect — dados resolvem no servidor em paralelo
- SEO: HTML completo no primeiro byte, sem hidratação para conteúdo estático
- Segredos seguros: API keys e queries ficam no servidor, nunca no bundle
As armadilhas que me pegaram
// ARMADILHA 1: passar função de Server pra Client
// Server Component NÃO pode passar callbacks pra Client Component
// (funções não serializam pela fronteira)
// ERRADO:
function ServerParent() {
const handleClick = () => console.log("oi"); // server-side
return <ClientChild onClick={handleClick} />; // ❌ erro
}
// CERTO: passe dados serializáveis, lógica fica no client
function ServerParent() {
return <ClientChild projectId={42} />; // ✅ número serializa
}
// ARMADILHA 2: usar API de browser em Server Component
function Bad() {
const w = window.innerWidth; // ❌ window não existe no servidor
return <div>{w}</div>;
}A fronteira server/client só aceita dados serializáveis: strings, números, objetos planos, arrays. Funções, classes, Dates complexas e Symbols não atravessam. Esse é o erro mais comum e o compilador nem sempre avisa de forma clara.
Vale a pena para o seu projeto?
Depende. Para apps com muito conteúdo dinâmico, fetching pesado e necessidade de SEO, RSC é transformador. Para uma SPA pequena e interativa como este portfólio, o overhead de complexidade não compensa — Vite + React Router client-side com HTML pré-gerado entrega Core Web Vitals excelentes sem o peso conceitual do RSC. Use a ferramenta certa, não a mais nova.
Se você está começando um projeto novo com Next.js em 2026, RSC já é o caminho default e vale aprender. Se tem um SPA Vite funcionando bem, não migre por FOMO. RSC resolve problemas específicos de fetching e bundle — se você não tem esses problemas, não precisa da solução.