Cache
Entenda as quatro camadas de cache no Next.js -- memoização de requisição, cache de dados, cache de rota completa e cache do roteador.
Busque em todas as páginas da documentação
Entenda as quatro camadas de cache no Next.js -- memoização de requisição, cache de dados, cache de rota completa e cache do roteador.
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥
Cartão de receita de referência rápida -- pronto para copiar e colar.
// Camada 1: Memoização de Requisição (automática para fetch, manual para outras)
// O mesmo URL de fetch é desduplicado dentro de um único passe de renderização
const data = await fetch("https://api.example.com/user/1"); // chamado em 3 componentes, apenas 1 requisição
// Memoização manual para chamadas não-fetch
import { cache } from "react";
export const getUser = cache(async (id: string) => {
return db.user.findUnique({ where: { id } });
});
// Camada 2: Cache de Dados (persiste entre requisições)
await fetch(url, { next: { revalidate: 3600 } }); // cacheado por 1 hora
await fetch(url, { cache: "no-store" }); // pula o cache de dados
await fetch(url, { next: { tags: ["users"] } }); // tag para invalidação
// Camada 3: Cache de Rota Completa (páginas estáticas no tempo de build)
// Automático para rotas sem dados dinâmicos
// Camada 4: Cache do Roteador (lado do cliente, em memória)
// Automático para pré-busca de <Link> e navegação de voltar/avançarQuando usar isso: Você precisa entender por que seus dados estão desatualizados, por que uma página não está atualizando ou como otimizar o desempenho aproveitando a camada de cache correta.
// lib/data.ts -- demonstrando todas as camadas de cache
import { cache } from "react";
import { db } from "@/lib/db";
// ---- Camada 1: Memoização de Requisição ----
// Esta função pode ser chamada de múltiplos Server Components
// no mesmo passe de renderização -- apenas uma consulta ao DB é executada
export const getCurrentUser = cache(async () => {
const session = await getSession();
if (!session) return null;
return db.user.findUnique({ where: { id: session.userId } });
});
// ---- Camada 2: Cache de Dados ----
export async function getProducts() {
const res = await fetch("https://api.example.com/products", {
next: { revalidate: 600, tags: ["products"] },
});
return res.json() as Promise<Product[]>;
}
// Sem cache -- sempre atualizado
export async function getCartItems(userId: string) {
const res = await fetch(`https://api.example.com/cart/${userId}`, {
cache: "no-store",
});
return res.json() as Promise<CartItem[]>;
}// app/layout.tsx -- getCurrentUser chamado aqui...
import { getCurrentUser } from "@/lib/data";
export default async function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
const user = await getCurrentUser(); // Requisição 1 (chamada real ao DB)
return (
<html lang="en">
<body>
<nav>
<span>{user?.name ?? "Guest"}</span>
</nav>
{children}
</body>
</html>
);
}// app/dashboard/page.tsx -- ...e também chamado aqui (desduplicado)
import { getCurrentUser } from "@/lib/data";
export default async function DashboardPage() {
const user = await getCurrentUser(); // Requisição 2 (memoizada -- sem chamada ao DB)
return <h1>Welcome back, {user?.name}</h1>;
}O que isso demonstra:
React.cache desduplicando uma chamada de banco de dados entre dois Server Components na mesma renderizaçãonext.revalidate colocando resultados de fetch no Cache de Dadoscache: "no-store" ignorando o Cache de Dados para dados específicos do usuáriogetCurrentUser() sem disparar duas consultasfetch é chamado com a mesma URL e opções, o React retorna o resultado memoizado. Para chamadas não-fetch (banco de dados, ORM), envolva a função com React.cache(). A memoização é limpa após a conclusão da renderização.next.revalidate para expiração baseada em tempo e next.tags para invalidação sob demanda via revalidateTag().cookies(), headers(), searchParams, ou cache: "no-store") são excluídas.<Link>, a próxima página pode já estar em cache. O cache do roteador tem diferentes tempos de vida: 30 segundos para páginas dinâmicas, 5 minutos para páginas estáticas (estes são os padrões e configuráveis no Next.js 15+).Optando por sair de todos os caches para uma rota:
// app/real-time/page.tsx
export const dynamic = "force-dynamic"; // pula o Cache de Rota Completa
export const fetchCache = "force-no-store"; // pula o Cache de Dados para todos os fetchesUsando unstable_cache para dados não-fetch:
import { unstable_cache } from "next/cache";
const getCachedPosts = unstable_cache(
async () => db.post.findMany(),
["all-posts"], // partes da chave do cache
{
tags: ["posts"],
revalidate: 3600,
}
);Controlando o comportamento do Cache do Roteador:
// next.config.ts
import type { NextConfig } from "next";
const config: NextConfig = {
experimental: {
staleTimes: {
dynamic: 0, // não cachear páginas dinâmicas no cliente
static: 300, // cachear páginas estáticas por 5 minutos
},
},
};
export default config;// React.cache preserva a assinatura da função
import { cache } from "react";
const getUser = cache(
async (id: string): Promise<User | null> => {
return db.user.findUnique({ where: { id } });
}
);
// getUser: (id: string) => Promise<User | null>
// Tipos de configuração de segmento
export const dynamic: "auto" | "force-dynamic" | "force-static" | "error" = "auto";
export const revalidate: number | false = 60;
export const fetchCache: "auto" | "default-cache" | "only-cache" |
"force-cache" | "force-no-store" | "default-no-store" | "only-no-store" = "auto";Confundir memoização de requisição com Cache de Dados -- A memoização de requisição é por renderização e efêmera; o Cache de Dados persiste entre requisições. Correção: Use React.cache() para desduplicação por requisição e next.revalidate / next.tags para cache persistente.
Cache do Roteador servindo páginas desatualizadas -- Após uma mutação, o Cache do Roteador do lado do cliente pode ainda servir a página antiga durante a navegação de voltar/avançar. Correção: Chame router.refresh() no Client Component após uma Server Action, ou configure staleTimes para reduzir a duração do cache do lado do cliente.
cache: "force-cache" não é sempre o padrão -- No Next.js 15+, o padrão é cache: "auto", que pode variar dependendo do contexto (funções dinâmicas, configuração de rota). Correção: Seja explícito sobre o comportamento de cache definindo cache ou next.revalidate em cada fetch.
Colisões de chave unstable_cache -- Se duas chamadas unstable_cache compartilham as mesmas partes de chave, mas retornam formas de dados diferentes, você obtém cache corrompido. Correção: Use arrays de chaves únicos e descritivos.
Middleware e Edge Runtime não compartilham caches -- O Cache de Dados é por região de implantação. Middleware executando na edge pode não ver o mesmo cache que uma função de servidor Node.js. Correção: Esteja ciente dos limites de cache em implantações multirregionais.
| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
React.cache() | Você precisa de desduplicação por requisição para chamadas não-fetch | Você precisa que os dados persistam entre requisições |
unstable_cache | Você precisa de semântica de Cache de Dados para chamadas de banco de dados ou ORM | fetch simples com next.revalidate funciona |
| Redis ou Memcached | Você precisa de um cache compartilhado entre múltiplas instâncias de servidor | O cache integrado do Next.js é suficiente |
SWR stale-while-revalidate | Você quer cache do lado do cliente com revalidação automática | O cache do lado do servidor cobre suas necessidades |
cache: "no-store" em todos os lugares | Os dados devem estar sempre atualizados (dashboards em tempo real) | Você pode tolerar dados desatualizados para melhor desempenho |
import { cache } from "react";
import { db } from "@/lib/db";
export const getUser = cache(async (id: string) => {
return db.user.findUnique({ where: { id } });
});React.cache() para desduplicação por requisiçãocache: "auto", não force-cache como no Next.js 14cache ou next.revalidate em cada fetchstaleTimes em next.config.tsexport const dynamic = "force-dynamic";
export const fetchCache = "force-no-store";force-dynamic pula o Cache de Rota Completaforce-no-store pula o Cache de Dados para todos os fetches na rotarouter.refresh() no Client Component ou reduza staleTimes na configuraçãounstable_cacheimport { cache } from "react";
const getUser = cache(
async (id: string): Promise<User | null> => {
return db.user.findUnique({ where: { id } });
}
);
// getUser: (id: string) => Promise<User | null>React.cache() fornece apenas desduplicação por requisição; os dados não persistem entre requisiçõesunstable_cache fornece semântica de Cache de Dados (persiste entre requisições, suporta tags e revalidação)unstable_cache para chamadas de banco de dados ou ORM que precisam de cache entre requisições// next.config.ts
const config: NextConfig = {
experimental: {
staleTimes: {
dynamic: 0, // não cachear páginas dinâmicas no cliente
static: 300, // cachear páginas estáticas por 5 minutos
},
},
};export const fetchCache:
| "auto"
| "default-cache"
| "only-cache"
| "force-cache"
| "force-no-store"
| "default-no-store"
| "only-no-store" = "auto";Revisado por Chris St. John·Última atualização: 7 de jul. de 2026
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥