Capítulo 6 de 456
Decidir onde cada parte da UI roda: Server Components (padrão) buscam dados e reduzem JS enviado ao cliente; Client Components entram só onde há interatividade, estado ou APIs de browser.
"use client"): necessário para estado, event handlers, lifecycle (useEffect), APIs de browser (localStorage, window) e custom hooks."use client" como boundary: marca a fronteira entre o module graph do servidor e do cliente; uma vez marcado, todos os imports e componentes renderizados diretamente por esse arquivo entram no bundle do cliente (não se aplica a Server Components passados como children/props).children/prop para Client Components (ex.: <Modal><Cart /></Modal>), permitindo nesting visual sem incluir o Server Component no bundle do cliente.ThemeProvider) e importe-o num Server Component como layout, mantendo o provider o mais fundo possível na árvore.server-only / client-only: pacotes npm opcionais que forçam erro de build se um módulo server-only for importado no cliente (ou vice-versa); variáveis de ambiente sem prefixo NEXT_PUBLIC_ já são substituídas por string vazia no bundle do cliente por padrão.// app/ui/counter.tsx
'use client'
import { useState } from 'react'
export default function Counter() {
const [count, setCount] = useState(0)
return (
<div>
<p>{count} likes</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
)
}
// app/ui/modal.tsx
'use client'
export default function Modal({ children }: { children: React.ReactNode }) {
return <div>{children}</div>
}
// app/page.tsx
import Modal from './ui/modal'
import Cart from './ui/cart'
export default function Page() {
return (
<Modal>
<Cart />
</Modal>
)
}
Cart) renderizado dentro de Client Component (Modal) via slot de children, sem entrar no bundle do cliente.// lib/data.js
import 'server-only'
export async function getData() {
const res = await fetch('https://external-service.com/data', {
headers: { authorization: process.env.API_KEY },
})
return res.json()
}
layout.tsx inteiro como "use client" por causa de um componente interativo: aumenta o bundle desnecessariamente; extraia só o componente interativo (ex.: <Search />) como Client Component e mantenha o resto Server.useState diretamente em Server Component: gera erro porque o Next.js não sabe que ele usa client-only features; envolva-o num wrapper próprio com "use client".<html> inteiro: dificulta a otimização de partes estáticas; envolva só {children}.server-only."use client" marca uma fronteira de module graph, tudo que esse arquivo importa e renderiza diretamente vai para o bundle do cliente, exceto Server Components passados como children/props.{children} o mais fundo possível na árvore, não a app inteira.server-only garante em build time que segredos não vazem para o cliente; variáveis sem NEXT_PUBLIC_ já são zeradas no bundle por padrão, mas isso não substitui a proteção explícita.use()."use server") usam a mesma lógica de module boundary vista aqui.