Partial Hydration é a técnica de não hidratar a página inteira. Só as partes interativas.
O Problema da Full Hydration
React tradicional:
- Servidor renderiza todo o HTML
- Cliente baixa todo o JavaScript
- Cliente re-executa todo o React para "hidratar"
Mesmo componentes 100% estáticos (texto, imagens) são hidratados.
Exemplo
// 95% estático, 5% interativo
export default function BlogPost() {
return (
<article>
<h1>Título do Post</h1>
<p>Parágrafo longo...</p>
<p>Mais texto...</p>
<p>Ainda mais texto...</p>
<LikeButton /> {/* Só isso é interativo! */}
</article>
);
}
React hidrata tudo, incluindo <h1>, <p>, etc., que nunca mudam.
Partial Hydration: Só O Necessário
Com Partial Hydration, hidratamos apenas <LikeButton>.
Astro Islands
Astro é o pioneiro. Componentes são estáticos por padrão:
---
// BlogPost.astro
import LikeButton from './LikeButton.jsx';
---
<article>
<h1>Título do Post</h1>
<p>Texto estático...</p>
<!-- Hidrata APENAS quando visível -->
<LikeButton client:visible />
</article>
Diretivas:
client:load- Hidrata no page loadclient:idle- Hidrata quando browser idleclient:visible- Hidrata quando entra na viewportclient:only- Só no cliente (sem SSR)
Resultado
Página de blog Astro:
- JavaScript: 5KB (só LikeButton)
Mesma página React:
- JavaScript: 200KB (React + todos componentes)
40x menos JavaScript.
Next.js Server Components
No App Router, componentes são server-only por padrão:
// app/post/page.jsx (Server Component)
import LikeButton from './LikeButton'; // Client Component
export default async function Post() {
const post = await getPost();
return (
<article>
<h1>{post.title}</h1>
<p>{post.content}</p>
<LikeButton postId={post.id} /> {/* Só isso hidrata */}
</article>
);
}
// LikeButton.jsx (Client Component)
'use client';
export default function LikeButton({ postId }) {
const [likes, setLikes] = useState(0);
return <button onClick={() => setLikes(likes + 1)}>❤️ {likes}</button>;
}
Server Components não enviam JavaScript. Só o <LikeButton> é hidratado.
Qwik: Zero Hydration
Qwik vai além: não há hydration. Só lazy-load quando interagir.
import { component$, useSignal } from '@builder.io/qwik';
export const Counter = component$(() => {
const count = useSignal(0);
return (
<button onClick$={() => count.value++}>
Clicks: {count.value}
</button>
);
});
Quando você clica:
- Qwik baixa o handler (
onClick$) - Executa
- Atualiza o DOM
Não há hydration prévia. JavaScript total inicial: ~1KB.
Performance: Comparação Real
Landing page com hero, features, testimonials, footer + 1 botão de newsletter:
React (Full Hydration)
- JavaScript: 180KB
- TTI: 2.3s
Astro (Partial Hydration)
- JavaScript: 12KB (só botão newsletter)
- TTI: 0.4s
Qwik (Zero Hydration)
- JavaScript: 1KB
- TTI: 0.05s
180x menos JavaScript com Qwik vs React.
Trade-offs
Astro/Next.js Server Components
✅ Reduz drasticamente JavaScript
✅ Fácil adotar (componentes isolados)
❌ Arquitetura mais complexa (client/server boundary)
Qwik
✅ Performance insana
✅ Escala para apps gigantes
❌ Ecossistema pequeno
❌ Curva de aprendizado alta
Quando Usar?
Partial Hydration (Astro, Next.js SC)
✅ Sites de conteúdo (blogs, marketing)
✅ E-commerce (produtos estáticos + cart interativo)
✅ Dashboards com sections estáticas
Zero Hydration (Qwik)
✅ Apps que precisam performance extrema
✅ Mobile-first (redes lentas)
✅ Disposto a aprender novo paradigma
Implementação: Next.js Server Components
// app/dashboard/page.jsx (Server)
import UserInfo from './UserInfo'; // Server
import Chart from './Chart'; // Client
export default async function Dashboard() {
const user = await getUser();
const stats = await getStats(); // Fetch no servidor
return (
<div>
<UserInfo user={user} /> {/* Estático, 0KB JS */}
<Chart data={stats} /> {/* Interativo, 50KB JS */}
</div>
);
}
// Chart.jsx (Client)
'use client';
import { LineChart } from 'recharts';
export default function Chart({ data }) {
return <LineChart data={data} />; // Hidrata
}
Conclusão: Partial Hydration é o futuro. Full hydration é desperdício de recursos.