Capítulo 45 de 456

ISR with Cache Components

Core Idea

Com cacheComponents + partialPrefetching, toda rota tem primeira visita instantânea, mesmo URLs não incluídas no build: rotas prerenderizadas em generateStaticParams servem página completa; rotas não listadas servem um App Shell instantâneo e fazem upgrade em background. Equivalente moderno a fallback: true do Pages Router.

Key Concepts

  • App Shell: parte genérica e reutilizável da página que não depende de dados da URL; servida instantaneamente para params desconhecidos.
  • generateStaticParams: define quais combinações de params são prerenderizadas no build; params fora dessa lista ficam "não resolvidos" até o upgrade.
  • Suspense dentro do componente, não acima dele: o await params deve ficar dentro de um componente envolto em <Suspense>, mesmo para params conhecidos, para que o App Shell seja gerado corretamente para uma única rota compartilhada.
  • Upgrade em background: após a primeira visita (ou um prefetch via <Link>/router.prefetch), Next.js renderiza a página com os params agora conhecidos; visitas seguintes recebem o resultado atualizado do cache.
  • Resolução de params em ordem de rota: um param não coberto por generateStaticParams fica não resolvido e impede que params mais profundos façam upgrade.
  • 'use cache' a nível de módulo: cacheia todas as funções exportadas de um arquivo (ex.: camada de dados), permitindo que seus resultados entrem no shell estático.

Code Examples

// next.config.ts
const nextConfig: NextConfig = {
  cacheComponents: true,
  partialPrefetching: true,
}
  • O que demonstra: as duas flags necessárias; cacheComponents produz o App Shell, partialPrefetching faz o upgrade.
// app/[category]/layout.tsx
async function CategoryHeader({ params }: Pick<LayoutProps<'/[category]'>, 'params'>) {
  const { category } = await params
  const data = await getCategory(category)
  return <div><h1>{data?.name ?? 'Category'}</h1></div>
}

export default function CategoryLayout(props: LayoutProps<'/[category]'>) {
  return (
    <div>
      <Suspense fallback={<div>Loading...</div>}>
        <CategoryHeader params={props.params} />
      </Suspense>
      {props.children}
    </div>
  )
}
  • O que demonstra: await params isolado num componente filho dentro de <Suspense>, permitindo gerar o App Shell mesmo para categorias conhecidas em generateStaticParams.

Reference Tables

Resultado do upgradeCondição
Página totalmente estáticaTodo acesso a dado é cacheado e todos os params resolvidos
Página cacheada com fallbacksParams resolvidos, mas ainda há dado não cacheado ou API de runtime (cookies, headers) em <Suspense>
Fica sem upgradeParam não coberto por generateStaticParams bloqueia upgrade de params mais profundos
Migrando do Pages RouterEquivalente em Cache Components
fallback: true em getStaticPathsComportamento padrão com cacheComponents
router.isFallbackNão é necessário; o shell estático já cobre isso
getStaticProps com revalidate'use cache' com cacheLife
getStaticPathsgenerateStaticParams

Anti-patterns

  • Fazer await params diretamente no layout/page acima do <Suspense>: ata o App Shell àquela URL específica em vez de gerar um shell genérico reutilizável.
  • Prerenderizar toda rota possível: aumenta tempo de build e storage sem necessidade; prefira prerenderizar só rotas populares/previsíveis e deixar o resto para upgrade sob demanda.

Key Takeaways

  1. O App Shell para params não listados só é servido a partir do Next.js 16.3; versões anteriores esperam um render completo no servidor.
  2. Um prefetch (link em viewport ou router.prefetch) conta como a "primeira visita" que dispara o upgrade em background.
  3. Manter o await params dentro do Suspense boundary, mesmo em rotas conhecidas, é o que garante App Shell compartilhado.
  4. Nem toda rota precisa ser prerenderizada; escolher com base em popularidade/previsibilidade economiza build time.

Connects To

  • Instant navigation (ch046): App Shell e validação de navegações instantâneas usam os mesmos conceitos de Suspense/cache.
  • ISR (ch044): versão sem Cache Components do mesmo problema (revalidação de páginas estáticas).
  • generateStaticParams: API central para controlar quais combinações de params são prerenderizadas.