O Next.js 15 foi uma versão de mudanças de comportamento, mais do que de recursos chamativos. Ele tornou o cache explícito, transformou as APIs de requisição em assíncronas e trouxe o React 19 para o App Router. Este site, inclusive, roda em Next.js 15.
Neste guia você vai entender cada mudança, o motivo por trás dela e como migrar um projeto existente sem sustos.
Criando e atualizando um projeto
npx create-next-app@15 meu-app # projeto novo na linha 15
npx @next/codemod@canary upgrade latest # atualiza um projeto existente e roda os codemodsO comando de upgrade atualiza next, react e react-dom e aplica automaticamente boa parte das mudanças de código descritas abaixo.
APIs de requisição agora são assíncronas
Esta é a mudança que mais quebra código. Tudo que depende da requisição passou a devolver uma Promise: cookies(), headers(), draftMode() e as props params e searchParams de páginas, layouts e rotas.
export default function Pagina({ params }: { params: { slug: string } }) {
return <h1>{params.slug}</h1>;
}export default async function Pagina({
params,
}: {
params: Promise<{ slug: string }>;
}) {
const { slug } = await params;
return <h1>{slug}</h1>;
}import { cookies, headers } from "next/headers";
export default async function Painel() {
const tema = (await cookies()).get("tema")?.value ?? "escuro";
const agente = (await headers()).get("user-agent");
return <p>{tema} · {agente}</p>;
}Por quê? Com as APIs assíncronas, o servidor pode começar a renderizar tudo que não depende da requisição antes de os dados dela estarem prontos. Isso prepara o terreno para renderização parcial (parte estática, parte dinâmica na mesma página).
Em Client Components, que não podem ser async, use o use do React para ler a Promise:
"use client";
import { use } from "react";
export default function Cliente({ params }: { params: Promise<{ id: string }> }) {
const { id } = use(params);
return <p>{id}</p>;
}O codemod next-async-request-api converte a maior parte dos casos automaticamente.
O cache deixou de ser implícito
No Next.js 14, muita coisa era cacheada por padrão, e isso confundia: dados desatualizados apareciam sem motivo aparente. O 15 inverteu a lógica.
Para cachear, agora você pede explicitamente:
// Um fetch específico
const res = await fetch("https://api.exemplo.com/produtos", {
cache: "force-cache",
});
// Revalidar a cada hora
const posts = await fetch("https://api.exemplo.com/posts", {
next: { revalidate: 3600 },
});// Todo o segmento
export const dynamic = "force-static";
export const revalidate = 3600;export const dynamic = "force-static"; // volta a tornar o GET estático
export async function GET() {
return Response.json({ ok: true });
}React 19
O App Router no Next.js 15 usa o React 19, que traz:
- Actions: funções assíncronas passadas para
<form action>, com estado de envio gerenciado pelo React. useActionState: estado e resultado de uma action (substitui o antigouseFormState).useFormStatus: saber se o formulário pai está enviando.useOptimistic: atualizar a interface antes da resposta do servidor.use: ler Promises e contextos, inclusive condicionalmente.refcomo prop comum:forwardRefdeixa de ser necessário.- Metadados no componente:
<title>e<meta>renderizados em qualquer lugar sobem para o<head>.
"use client";
import { useActionState } from "react";
import { assinar } from "./actions";
export function Newsletter() {
const [estado, acao, enviando] = useActionState(assinar, { mensagem: "" });
return (
<form action={acao}>
<input name="email" type="email" required />
<button disabled={enviando}>{enviando ? "Enviando..." : "Assinar"}</button>
<p>{estado.mensagem}</p>
</form>
);
}"use server";
export async function assinar(_anterior: { mensagem: string }, form: FormData) {
const email = form.get("email");
// ... grava no banco
return { mensagem: `Inscrito: ${email}` };
}O React Compiler, que aplica memoização automaticamente e reduz a necessidade de useMemo e useCallback, pode ser ativado de forma experimental com experimental.reactCompiler no next.config.
Turbopack no desenvolvimento
O Turbopack, o empacotador escrito em Rust, ficou estável para o servidor de desenvolvimento:
next dev --turbopackOs ganhos anunciados pela Vercel foram significativos no início do servidor e na atualização após salvar arquivos, especialmente em projetos grandes. O suporte ao next build com Turbopack chegou depois, em fase experimental, dentro da linha 15.
next.config.ts
A configuração agora pode ser escrita em TypeScript, com autocomplete:
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
reactStrictMode: true,
images: { formats: ["image/avif", "image/webp"] },
};
export default nextConfig;after(): trabalho depois da resposta
Executa código depois que a resposta já foi enviada ao usuário, ideal para logs, analytics e sincronizações que não devem atrasar a página. Chegou como experimental no 15.0 e ficou estável no 15.1:
import { after } from "next/server";
export default async function Pagina() {
after(async () => {
await registrarVisualizacao(); // não atrasa a renderização
});
return <h1>Olá</h1>;
}next/form
O componente <Form> estende o <form> HTML com navegação do lado do cliente, prefetch da página de destino e envio progressivo. Perfeito para formulários de busca que levam para uma página de resultados:
import Form from "next/form";
export function Busca() {
return (
<Form action="/busca">
<input name="q" placeholder="Buscar..." />
<button type="submit">Buscar</button>
</Form>
);
}Ao enviar, o usuário vai para /busca?q=... sem recarregar a página inteira.
Outras melhorias
- Indicador de rota estática durante o desenvolvimento, mostrando quais páginas serão geradas no build.
instrumentation.tsestável, comonRequestErrorpara enviar erros do servidor a ferramentas de observabilidade.- Segurança em Server Actions: IDs imprevisíveis e remoção de actions não utilizadas do build.
- Melhorias para self-hosting: controle de
Cache-Controle otimização de imagens usandosharpautomaticamente. - ESLint 9 suportado.
Passo a passo de migração
Crie uma branch e rode o upgrade
git switch -c chore/next-15 npx @next/codemod@canary upgrade latestRevise as APIs assíncronas
Procure usos de
params,searchParams,cookies()eheaders()que o codemod não converteu (ele deixa comentários@next-codemod-errornos casos que não conseguiu resolver).Decida o cache de propósito
Liste os
fetche Route HandlersGETque dependiam do cache implícito e adicionecache: "force-cache",revalidateoudynamic = "force-static"onde fizer sentido.Atualize bibliotecas para o React 19
Bibliotecas de UI e de formulários podem precisar de versões novas. Rode
npm ls reactpara achar dependências presas ao React 18.Compile e teste
npm run build npm run startConfira no resumo do build quais rotas ficaram estáticas (○) e quais dinâmicas (ƒ) e compare com o que você esperava.
Tabela de referência do Next.js 15
Next.js 15: referência rápida
Comandos e APIs mais usados.
CLI
No terminal
Dados e cache
Explícito no Next.js 15
Requisição
Agora assíncronas
React 19
Hooks e padrões novos
Referências
- Anúncio oficial do Next.js 15: a lista completa de mudanças.
- Guia de migração para a versão 15: passo a passo oficial.
- Documentação do Next.js: App Router, cache e APIs.
- React 19: o que mudou no React.
5 perguntas sobre o Next.js 15.
Como ler params em uma página do Next.js 15?
Não foi dessa vez. Explicação:
params passou a ser uma Promise e precisa ser aguardado.



