spinny:~/writing $ less nextjs-16-cache-components.md
12Durante anos, uma das perguntas mais irritantes no Next.js foi: “Esta página é estática ou dinâmica?”. Parece uma pergunta simples, até você adicionar uma chamada para `cookies()`, um `fetch` com opções diferentes, um cliente de banco de dados, um CMS, um carrinho de compras ou um conteúdo personalizado.34Next.js 16 é interessante porque tenta tornar essa conversa menos misteriosa. Isso não elimina a complexidade, mas muda o modelo mental: as rotas são dinâmicas por padrão, o cache se declara onde necessário e `Suspense` se torna a maneira natural de compor shells rápidos com partes que permanecem atualizadas.56O recurso a ser entendido são os componentes de cache. Stable Turbopack, React Compiler, `proxy.ts` e as novas APIs de invalidação são importantes, mas giram em torno do mesmo problema: construir aplicativos rápidos sem ter que adivinhar o que a estrutura decidiu nos bastidores.78## Porque essa coisa importa910Em um aplicativo real você não tem apenas “páginas estáticas” e “páginas dinâmicas”. Você tem peças diferentes com necessidades diferentes.1112A ficha do produto pode mudar algumas vezes ao dia. O preço pode mudar com mais frequência. A disponibilidade deve estar quase ativa. O nome de usuário é pessoal. As avaliações podem ser transmitidas. A barra lateral pode ser estável. O carrinho não.1314Se você tratar tudo como uma unidade, sempre terminará em um de dois extremos:1516- cache agressivo e risco de ver dados antigos;17- renderização dinâmica em todos os lugares e desempenho pior que o necessário.1819Cache Components serve justamente para evitar essa falsa escolha.2021## O modelo na prática2223Com `cacheComponents: true`, você pode declarar o que pode ser armazenado em cache usando `"use cache"`. Então você pode associar duração e tags a `cacheLife()` e `cacheTag()`. As partes dinâmicas permanecem dinâmicas e podem ser isoladas com `Suspense`.2425```mermaid26flowchart TD27 Request[Solicitação do usuário] --> Shell[Shell em cache]28 Request --> Dynamic[Seções dinâmicas]29 Shell --> FirstPaint[Primeiro conteúdo rápido]30 Dynamic --> Stream[Streaming dentro do Suspense]31 Stream --> Complete[Página inteira]32```3334A configuração é pequena:3536```typescript37// next.config.ts38import type { NextConfig } from 'next';3940const nextConfig: NextConfig = {41 cacheComponents: true,42};4344export default nextConfig;45```4647A grande mudança não está na configuração. É como você começa a escrever os componentes.4849```tsx50// app/products/[slug]/page.tsx51import { Suspense } from 'react';52import { cacheLife, cacheTag } from 'next/cache';5354async function getProduct(slug: string) {55 'use cache';5657 cacheLife('hours');58 cacheTag(`product:${slug}`);5960 return db.product.findUnique({ where: { slug } });61}6263async function ProductDetails({ slug }: { slug: string }) {64 const product = await getProduct(slug);6566 return (67 <section>68 <h1>{product.name}</h1>69 <p>{product.description}</p>70 </section>71 );72}7374async function LiveInventory({ slug }: { slug: string }) {75 const inventory = await db.inventory.findFirst({ where: { slug } });76 return <p>{inventory.quantity} pezzi disponibili</p>;77}7879export default async function ProductPage({ params }: { params: Promise<{ slug: string }> }) {80 const { slug } = await params;8182 return (83 <>84 <ProductDetails slug={slug} />85 <Suspense fallback={<p>Controllo disponibilità...</p>}>86 <LiveInventory slug={slug} />87 </Suspense>88 </>89 );90}91```9293A página não precisa estar toda armazenada em cache ou totalmente dinâmica. A ficha do produto pode ser rápida e reutilizável. O estoque pode permanecer atualizado. O usuário vê algo imediatamente, sem esperar pela parte mais lenta.9495## `use cache` é documentação executável9697O que eu gosto em `"use cache"` é que ele força você a deixar uma intenção explícita. Ao ler uma função, você imediatamente entende que alguém decidiu: “esses dados podem ser reutilizados”.9899É especialmente útil quando você não está usando `fetch`. Muitos aplicativos leem dados do Prisma, Drizzle, SDKs internos, clientes CMS ou funções de serviço. Nesses casos o antigo raciocínio baseado apenas nas opções `fetch` não era suficiente.100101Uma regra prática:102103- conteúdo de cachea relativamente estável;104- use tags granulares;105- deixa permissões dinâmicas, sessões, carrinhos, notificações e estados transacionais;106- coloque partes lentas dentro de `Suspense`;107- medir antes de dizer "melhoramos o desempenho".108109## Invalidar sem jogar tudo fora110111O cache só será útil se você puder atualizá-lo com precisão. Aqui `cacheTag`, `revalidateTag` e `updateTag` tornam-se importantes.112113Exemplo:114115```typescript116'use server';117118import { updateTag } from 'next/cache';119120export async function updateProductName(productId: string, name: string) {121 await db.product.update({122 where: { id: productId },123 data: { name },124 });125126 updateTag(`product:${productId}`);127}128```129130O detalhe importante é a tag. `product:${productId}` informa um limite preciso. `products` conta um balde enorme. A princípio, o enorme balde é confortável; depois de alguns meses, esse é o motivo pelo qual você invalida metade de um aplicativo para alterar um título.131132## Stable Turbopack: a parte que você ouve todos os dias133134Next.js 16 traz o Turbopack para o centro de desenvolvimento e construção. Não é o recurso mais poético, mas é o que você sente enquanto trabalha: servidor que inicia mais cedo, atualização mais rápida, compilações que deixam de parecer uma pausa forçada para o café.135136Dito isso, eu não migraria uma base de código cheia de plug-ins personalizados de olhos fechados. Eu verificaria:137138- construção local;139- importação fora do padrão;140- MDX, SVG e CSS;141- Plug-ins do Webpack restantes;142- páginas críticas;143- diferenças nos tempos de construção.144145Para novos projetos, eu começaria pelo padrão. Para os mais maduros, eu faria uma migração comedida.146147## Compilador React: remova o ruído, não o pensamento148149React Compiler 1.0 é estável e Next.js 16 oferece suporte com `reactCompiler`. A promessa é reduzir muita memorização manual: menos `memo`, menos `useMemo`, menos `useCallback` usado "por segurança".150151```typescript152// next.config.ts153import type { NextConfig } from 'next';154155const nextConfig: NextConfig = {156 reactCompiler: true,157};158159export default nextConfig;160```161162Eu não trataria isso como um pó mágico. O compilador ajuda quando o código segue bem as regras do React. Se os componentes tiverem efeitos colaterais estranhos, mutações ocultas ou ganchos mal utilizados, isso precisa ser corrigido primeiro.163164A maneira saudável de experimentar:1651661. atualizar `eslint-plugin-react-hooks`;1672. corrigir violações reais;1683. habilite-o em uma área controlada;1694. medir o tempo de construção e o comportamento;1705. remova a memorização manual somente quando ela não for mais necessária.171172O objetivo não é apagar todos os `useMemo`. O objetivo é parar de escrever memoizações preventivas porque temos medo de renderizar.173174## `proxy.ts` e o limite da rede175176O antigo `middleware.ts` torna-se `proxy.ts`. É uma mudança de nome, mas faz sentido: esse arquivo fica no limite da solicitação, não é um middleware genérico tradicional no estilo back-end.177178```typescript179// proxy.ts180import { NextRequest, NextResponse } from 'next/server';181182export default function proxy(request: NextRequest) {183 const isLoggedIn = Boolean(request.cookies.get('session'));184185 if (!isLoggedIn && request.nextUrl.pathname.startsWith('/dashboard')) {186 return NextResponse.redirect(new URL('/login', request.url));187 }188189 return NextResponse.next();190}191```192193A regra aqui é simples: mantenha o tamanho pequeno. Redirecionamento, roteamento de autenticação, cabeçalhos, reescritas essenciais. Se começar a parecer um segundo back-end, provavelmente está fazendo muito.194195## Como eu realmente migraria196197Eu não ativaria todos os recursos de uma vez. Eu faria isso:1981991. Eu atualizo Next, React e React DOM;2002. Eu lanço o codemod oficial;2013. Corrijo alterações importantes em `params`, `searchParams`, `cookies()`, `headers()` e `draftMode()`;2024. Eu migro `middleware.ts` para `proxy.ts`;2035. Verifico compilações e páginas críticas;2046. Eu habilito os componentes de cache em uma seção onde o cache atualmente cria atrito;2057. Defino convenções para tags e invalidação;2068. Eu tento o React Compiler separadamente;2079. comparação de métricas antes e depois.208209A boa migração não é aquela que utiliza todos os novos recursos. É o que torna o comportamento do aplicativo mais legível.210211## O que muda na forma de pensar212213A coisa mais útil sobre Next.js 16 é que ele força você a nomear melhor as intenções. Uma função não é apenas “obter o produto do banco de dados”. É "pegue o produto, posso armazená-lo em cache por horas, invalido-o com esta tag". Um componente não é apenas “renderizar a página”. É “este é o shell rápido, esta peça é pessoal, isso vem em streaming”.214215A princípio parece mais trabalho. Então se torna uma forma de calma. As decisões de desempenho não estão mais escondidas em uma combinação de padrões, heurísticas e memória tribal. Eles estão no código.216217## Fontes úteis218219- [Notas de versão do Next.js 16](https://nextjs.org/blog/next-16)220- [Componentes de cache - documentos Next.js](https://nextjs.org/docs/app/getting-started/cache-components)221- [usar cache - documentos Next.js](https://nextjs.org/docs/app/api-reference/directives/use-cache)222- [Compilador React v1.0](https://react.dev/blog/2025/10/07/react-compiler-1)223
:Next.js 16, Cache Components e React Compiler: o que realmente mudalines 1-223 (END) — press q to close