Boas Práticas de Padrões Next.js
Um resumo condensado das 25 melhores práticas mais importantes, extraídas de todas as páginas desta seção.
Busque em todas as páginas da documentação
Um resumo condensado das 25 melhores práticas mais importantes, extraídas de todas as páginas desta seção.
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥
server-only: Coloque import "server-only" no topo de qualquer módulo que toque em AUTH_SECRET, URLs de banco de dados ou chaves de assinatura para que um Client Component que o importe falhe na compilação em vez de vazar o valor para o pacote do navegador.httpOnly: true para bloquear o acesso JS, secure: true em produção para exigir HTTPS e sameSite: "lax" para proteção CSRF básica; sameSite: "none" adicionalmente requer secure: true ou o navegador descartará o cookie completamente.NextRequest, Não Request: Importe NextRequest/NextResponse de next/server para obter .nextUrl, .cookies, .geo e helpers estáticos como NextResponse.json() sem reconstruí-los em cima do Request da Web.{ params: Promise<{ ... }> }; desestruturar sem await params retorna uma Promise e sua busca silenciosamente retornará undefined.request.json em try/catch: Um corpo vazio ou malformado faz com que await request.json() lance um erro, então envolva-o e retorne { error: "Invalid JSON" } com status 400 - ou valide com safeParse do Zod para entrada totalmente tipada.new NextResponse(null, { status: 204 }); NextResponse.json(null, { status: 204 }) envia a string "null" como corpo e viola o contrato 204.updateMany({ where: { credits: { gt: 0 } }, data: { credits: { decrement: 1 } } }) ou "incremente primeiro, depois verifique, reverta em caso de overflow" para fechar a janela TOCTOU entre leitura e escrita.NEXT_PUBLIC_: Qualquer variável com o prefixo NEXT_PUBLIC_ é incorporada ao pacote do cliente no momento da compilação, portanto, reserve-a para chaves publicáveis e URLs públicas - URLs de banco de dados, chaves de API e segredos de assinatura devem permanecer apenas do lado do servidor.process.env Dinâmico no Cliente: O Next.js faz substituição estática de strings, não consulta em tempo de execução, então process.env[varName] é sempre undefined no código do cliente - apenas referências literais como process.env.NEXT_PUBLIC_APP_URL são incorporadas.process.env através de um esquema Zod em lib/env.ts para que variáveis ausentes ou malformadas falhem rapidamente com uma mensagem clara antes da primeira solicitação, e você obtenha um objeto env totalmente tipado gratuitamente.error.tsx Deve Ser um Client Component: React Error Boundaries dependem do ciclo de vida da classe, então todo error.tsx precisa de "use client" no topo; sem ele, a compilação falha e nenhuma boundary é instalada para esse segmento.global-error.tsx Renderiza Seu Próprio html/body: Quando o layout raiz falha, global-error.tsx substitui o documento inteiro, então ele deve renderizar <html><body>…</body></html>; ele também só ativa em produção (o dev mostra a sobreposição do Next.js).{ success: true; data: T } | { success: false; error: string } para falhas de validação esperadas, e reserve throw para erros inesperados que devem acionar o error.tsx mais próximo.redirect Fora de try/catch: redirect() (e notFound()) lançam um erro sentinela NEXT_REDIRECT, então um try/catch circundante engole a navegação - coloque a chamada após toda a lógica recuperável ou relance o sentinela.output: standalone e Copie Assets: output: "standalone" produz um servidor mínimo autônomo, mas .next/static e public/ não estão incluídos - copie-os para o diretório standalone (ou use um CDN/proxy reverso na frente) ou os assets estáticos resultarão em 404.HOSTNAME 0.0.0.0 no Docker: O servidor Next.js se vincula a 127.0.0.1 por padrão, o que é inacessível de fora de um contêiner; defina ENV HOSTNAME="0.0.0.0" (e ENV PORT=3000) no Dockerfile para que o mapeamento de porta funcione.runtime = "edge" é executado em um isolado V8 sem built-ins do Node - sem fs, path, child_process ou Buffer, e você deve usar globalThis.crypto; volte para "nodejs" sempre que precisar dessas APIs.metadataBase no Layout Raiz: Todas as URLs relativas em openGraph, twitter e alternates são resolvidas contra metadataBase; sem metadataBase: new URL("https://myapp.com"), suas imagens OG e canônicas são enviadas como caminhos relativos quebrados.generateMetadata para Páginas Dinâmicas: Para títulos, descrições e imagens OG por postagem, exporte async generateMetadata({ params }) (params é uma Promise no Next.js 15+) e estenda o pai através do argumento ResolvingMetadata em vez de duplicar campos.sitemap.ts e robots.ts: Exportar uma função padrão de app/sitemap.ts serve automaticamente /sitemap.xml e app/robots.ts serve automaticamente /robots.txt; divida em múltiplos Route Handlers de sitemap quando um site exceder o limite de 50.000 URLs do sitemap.i18n: O middleware de detecção de localidade deve pular _next, api e arquivos com extensões (por exemplo, matcher: ["/((?!_next|api|favicon.ico).*)"]) ou ele redirecionará assets estáticos para caminhos com prefixo de localidade e quebrará a página.generateStaticParams: Pré-renderize todas as localidades em tempo de compilação retornando cada uma de generateStaticParams; localidades ausentes resultarão em 404 silenciosos em produção, a menos que dynamicParams esteja habilitado.next/headers e next/cache em Testes: cookies(), headers(), revalidatePath e revalidateTag lançam erros fora do contexto de solicitação do Next.js, então substitua-os com vi.mock("next/headers", …) / vi.mock("next/cache", …) antes de importar o módulo sob teste.const jsx = await PostList(); render(jsx) em vez de render(<PostList />); também simule com vi.mock() antes de import() dinâmico para garantir que a simulação vença.Revisado por Chris St. John·Última atualização: 19 de jul. de 2026
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥