Capítulo 21 de 456

Adopting Partial Prefetching

Core Idea

Ative Partial Prefetching quando o app já usa Cache Components e você quer que cada <Link> prefetche apenas o App Shell compartilhado da rota (estático + conteúdo cacheado independente de URL), em vez de renderizar/prefetchar cada link separadamente.

Key Concepts

  • App Shell: conteúdo estático + cacheado que não depende da URL; um único App Shell é construído por rota e reutilizado por todos os links que apontam para ela.
  • partialPrefetching: flag em next.config.ts que ativa Partial Prefetching; requer cacheComponents: true habilitado antes.
  • <Link prefetch={true}>: com Partial Prefetching, deixa de incluir conteúdo dinâmico/URL-specific; passa a opt-in per-link prefetching que resolve params/searchParams além do App Shell.
  • URL data: params e searchParams (não cookies()/headers(), que variam por sessão, não por link); não pode ser incluído no App Shell compartilhado.
  • prefetch = 'partial': export route-segment-config que adota Partial Prefetching por rota individual, sem ligar a flag global (adoção incremental).
  • instant = false: export que opta uma rota fora da validação de instant-navigation, para adotar depois.
  • next-partial-prefetching-adoption skill: skill oficial (npx skills add vercel/next.js --skill next-partial-prefetching-adoption) que automatiza a auditoria e adoção.

Code Examples

import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  cacheComponents: true,
  partialPrefetching: true,
}

export default nextConfig
  • O que demonstra: Ativação da flag partialPrefetching, que exige cacheComponents já ligado.
// Cache com use cache para o conteúdo entrar no App Shell
async function getProducts() {
  'use cache'
  const res = await fetch('https://api.example.com/products')
  return res.json()
}

export default async function Page() {
  return <ProductList products={await getProducts()} />
}
  • O que demonstra: Padrão para preservar conteúdo não-cacheado dentro do App Shell após ativar a flag: envolver em 'use cache'.
// Empurrar params/searchParams pra dentro de um Suspense boundary
import { Suspense } from 'react'
import { ProductDetails } from './product-details'

export default function Page({ params }: PageProps<'/products/[slug]'>) {
  return (
    <ProductLayout>
      <Suspense fallback={<DetailsSkeleton />}>
        <ProductDetails params={params} />
      </Suspense>
    </ProductLayout>
  )
}
  • O que demonstra: Correção do insight "URL data outside of Suspense": passar a promise de params sem await no nível do Page, resolvendo dentro de um componente filho envolto em <Suspense>.

Reference Tables

<Link> propAntes (Cache Components default)Depois (Partial Prefetching)
<Link href="/x">Prefetch do render completo cacheadoCarrega só o App Shell compartilhado de /x
<Link href="/x" prefetch>Prefetch completo + conteúdo dinâmicoApp Shell + conteúdo URL-specific via per-link prefetching
<Link href="/x" prefetch={false}>Prefetch desabilitadoInalterado
Destino do linkRecomendação
Estático ou já cacheadoRemover prefetch={true} (redundante)
Conteúdo não-cacheado que precisa continuar prefetchedEnvolver em use cache, remover prefetch={true}
Depende de cookies()/headers()Cachear atrás do valor de sessão, remover prefetch={true}
Lê URL data (params/searchParams)Manter prefetch={true}
Conteúdo real-timeRemover prefetch={true}, deixar fazer stream

Anti-patterns

  • Ativar partialPrefetching sem auditar <Link prefetch={true}> existentes: pode reduzir silenciosamente o que era prefetchado antes, causando delay perceptível na navegação.
  • Ler params/searchParams fora de <Suspense> no Page: prende o App Shell a uma única URL, quebrando o compartilhamento entre links.

Key Takeaways

  1. Partial Prefetching só funciona com cacheComponents ativado; ative ambas as flags juntas.
  2. Após ligar a flag, audite cada <Link prefetch={true}> usando a tabela de recomendações: a maioria pode perder o prefetch={true} depois de cachear o conteúdo com use cache.
  3. params/searchParams nunca entram no App Shell compartilhado; mova a leitura para dentro de um <Suspense> filho.
  4. Adoção incremental via export const prefetch = 'partial' por rota, sem ligar a flag global, permite migrar app por app; remova os exports depois com o codemod remove-partial-prefetch.
  5. Use a skill next-partial-prefetching-adoption para automatizar auditoria e migração em vez de fazer manual.

Connects To

  • caching (Cache Components): pré-requisito obrigatório para Partial Prefetching.
  • instant-navigation: os insights de dev overlay (dynamic data during prefetching, URL data outside of Suspense) vêm desse sistema.
  • optimizing-prefetching: cobre quando vale o custo de per-link prefetching e padrões de cache por sessão.