- Artigos
- Desenvolvimento
- Extração de Payload no Nuxt 4: navegação mais rápida sem chamadas extras à API

Extração de Payload no Nuxt 4: navegação mais rápida sem chamadas extras à API
Se você já colocou em produção uma aplicação Nuxt com renderização no servidor, provavelmente já se beneficiou do sistema de payload sem perceber. Durante o SSR, os dados buscados com useAsyncData e useFetch são serializados e enviados ao navegador para que a hidratação não dispare requisições duplicadas. Esse mecanismo mantém a primeira renderização rápida e evita o clássico problema de “buscar duas vezes”.
A extração de payload leva essa ideia um passo além. Em vez de manter todos os dados serializados dentro do HTML, o Nuxt pode gravar um arquivo separado _payload.json ao lado de cada página pré-renderizada ou em cache. Quando o usuário navega no cliente até essa rota, o framework carrega o payload em cache diretamente. Seus componentes continuam hidratando com os mesmos dados, mas o backend recebe bem menos chamadas repetidas.
O que existe dentro de um arquivo de payload?
O payload do Nuxt é um objeto JavaScript exposto por useNuxtApp().payload. Ele armazena os resultados dos composables assíncronos, indexados pela chave que você passa ao useAsyncData ou pela chave gerada automaticamente pelo useFetch. O Nuxt serializa esses dados com devalue, o que significa que você não fica limitado a JSON puro. Dates, Maps, Sets, refs reativas e instâncias de NuxtError podem atravessar a transferência do servidor para o cliente quando configurados corretamente.
Em uma página de produto pré-renderizada, por exemplo, o HTML pode conter apenas a marcação e o código mínimo de inicialização, enquanto /products/widget/_payload.json guarda o registro do catálogo, itens relacionados e qualquer outro estado assíncrono resolvido durante a renderização. A navegação no cliente entre páginas em cache fica mais próxima de carregar assets estáticos do que de executar novamente sua camada de dados.
Por que a extração de payload importa em produção
Manter o payload inline no HTML funciona, mas tem trade-offs. Conjuntos grandes de dados incham o HTML, aumentam o Time to First Byte em requisições frias e reduzem a eficiência de cache, porque HTML e dados compartilham o mesmo documento. Extrair o payload para um arquivo dedicado traz três ganhos práticos:
- Respostas HTML menores na carga inicial quando você escolhe o modo de extração client.
- Cache amigável a CDN, já que o _payload.json pode ser cacheado junto com o HTML na Vercel, Netlify, Cloudflare e outras plataformas de edge.
- Menos chamadas à API durante navegação estilo SPA, o que faz diferença em sites ISR, SWR e estáticos com layouts compartilhados e fetches globais.
Para sites com muito conteúdo, páginas de marketing e catálogos de e-commerce, essa combinação costuma aparecer como menos tráfego na origem e transições mais fluidas entre rotas.
Onde o Nuxt 4 gera arquivos de payload
A extração de payload não é mais exclusividade do nuxt generate. No Nuxt 4, especialmente a partir da v4.3, os arquivos _payload.json são produzidos para:
- Rotas pré-renderizadas no momento do build
- Rotas ISR na primeira requisição, com regeneração conforme a janela de revalidação
- Rotas SWR que servem conteúdo stale enquanto atualizam em segundo plano
- Regras de cache configuradas via Nitro
Essa expansão é importante para projetos reais. Uma rota dinâmica como pages/blog/[slug].vue não precisa de um caminho em build time para cada artigo se você aplicar uma regra como /blog/**: { isr: 3600 }. O primeiro visitante dispara a renderização, e o Nuxt persiste HTML e payload para navegações futuras.
Configurando o payloadExtraction
O comportamento é controlado por experimental.payloadExtraction no nuxt.config.ts. O Nuxt oferece três modos:
- true — o payload é extraído para _payload.json tanto na renderização inicial quanto na navegação no cliente. Esse é o padrão atual no Nuxt 4.
- 'client' — o payload permanece inline no HTML na primeira requisição, mas arquivos separados são gerados para navegações subsequentes no cliente. Isso evita uma ida extra à rede na carga inicial, preservando transições rápidas depois. Projetos que miram compatibilidade com Nuxt 5 costumam tratar esse modo como padrão preferido.
- false — a extração é desativada. O payload fica inline no HTML e nenhum _payload.json é criado.
Uma configuração típica para uma loja híbrida pode ficar assim:
export default defineNuxtConfig({
experimental: {
payloadExtraction: 'client',
},
routeRules: {
'/': { prerender: true },
'/products/**': { isr: 3600 },
'/blog/**': { swr: true },
},
})Com essa configuração, a home fica totalmente estática, as páginas de produto revalidam a cada hora e os posts do blog podem servir conteúdo em cache imediatamente enquanto atualizam de forma assíncrona. Em todos os casos, as navegações podem reutilizar o payload extraído em vez de buscar novamente na sua API Laravel ou Node.
Combinando route rules com busca de dados
A extração de payload só ajuda quando suas páginas realmente populam o payload durante a renderização. Isso significa usar useAsyncData ou useFetch no setup, e não chamadas isoladas de $fetch que ignoram o pipeline de payload.
Veja uma página de artigo:
const route = useRoute()
const { data: article } = await useAsyncData(
`article-${route.params.slug}`,
() => $fetch(`/api/articles/${route.params.slug}`),
)
const { data: related } = await useAsyncData(
`related-${route.params.slug}`,
() => $fetch(`/api/articles/${route.params.slug}/related`),
)Quando a página é pré-renderizada ou cacheada via ISR, os dois conjuntos de dados são serializados. Em uma navegação posterior de /blog para /blog/meu-post, o Nuxt pode hidratar a partir do _payload.json em vez de fazer duas novas requisições à API. Se você tivesse usado apenas $fetch no onMounted, perderia essa otimização por completo.
Chaves, sharedPrerenderData e uma armadilha comum
A extração de payload funciona melhor quando as chaves são previsíveis e únicas. No Nuxt 4, sharedPrerenderData vem habilitado por padrão na geração estática. Durante o prerender, o Nuxt pode reutilizar entradas de payload entre páginas quando a mesma chave resolve para os mesmos dados. Isso acelera muito builds de sites grandes.
O risco aparece em rotas dinâmicas. Se você omitir uma chave explícita, o Nuxt pode gerar uma com base no arquivo, o que pode colidir entre páginas que buscam registros diferentes. O padrão seguro é incluir parâmetros de rota ou identificadores de entidade na chave:
// Inseguro em [slug].vue porque a chave ignora o slug
await useAsyncData(() => $fetch(`/api/pages/${route.params.slug}`))
// Seguro: a chave reflete o recurso buscado
await useAsyncData(route.params.slug, () =>
$fetch(`/api/pages/${route.params.slug}`),
)Isso importa em dois momentos: na deduplicação em build time e quando uma CDN serve arquivos de payload em cache para usuários reais. Uma chave errada pode causar vazamento de dados entre páginas, algo difícil de perceber no ambiente local.
Depurando o comportamento do payload em desenvolvimento
A extração de payload costumava ser verificada só depois de um build de produção. No Nuxt 4, ela também funciona em desenvolvimento quando nitro.static está habilitado ou quando a rota usa regras de prerender, isr, swr ou cache. Isso facilita muito confirmar a geração dos arquivos antes do deploy.
Verificações práticas:
- Execute nuxt generate ou um build de produção com regras de prerender e inspecione .output/public em busca de arquivos _payload.json.
- Abra a aba Network do DevTools durante navegação no cliente e observe requisições de payload em vez de chamadas duplicadas à API.
- Inspecione window.__NUXT__ na carga inicial e compare o que muda após navegar para uma rota em cache.
- Sobrescreva getCachedData apenas quando houver uma estratégia de cache deliberada; o padrão já lê dos stores de payload e static.
Quando desativar ou mudar o modo
A extração de payload não é obrigatória para todo app. Mantenha o payload inline com payloadExtraction: false quando:
- Suas páginas são majoritariamente renderizadas no cliente e nunca são pré-renderizadas ou cacheadas.
- Os arquivos de payload conteriam dados altamente específicos do usuário, que não devem ser cacheados na borda da CDN.
- Você está depurando inconsistências de hidratação e quer menos variáveis no meio do caminho.
Escolha 'client' quando a performance da primeira carga importa mais do que separar HTML e dados na requisição inicial. Mantenha true quando quiser granularidade máxima de cache para HTML e payload em todas as navegações.
Considerações finais
A extração de payload é um daqueles recursos do Nuxt que recompensa times que já pensam em modos de renderização. Se você combina routeRules, chaves consistentes no useAsyncData e o modo certo de payloadExtraction, obtém velocidade de site estático com o conforto de navegação SPA. O detalhe de implementação é um arquivo JSON ao lado do HTML. O resultado são menos chamadas à API, melhor aproveitamento da CDN e uma experiência visivelmente mais fluida para quem percorre páginas pré-renderizadas ou em cache.