Capítulo 165 de 456

generateViewport

Core Idea

Customize o viewport inicial da página (theme-color, escala, color-scheme) via objeto estático viewport ou função dinâmica generateViewport, ambos exclusivos de Server Components.

Key Concepts

  • viewport (objeto): export estático de Viewport para valores que não dependem de request.
  • generateViewport(): export de função async/sync quando o viewport depende de params ou dados externos.
  • Restrição de export único: não é possível exportar viewport e generateViewport no mesmo segmento.
  • Viewport não pode ser streamed: ao contrário de metadata, afeta o UI de carregamento inicial; se generateViewport cai pra request-time, a página bloqueia até resolver.
  • instant = false: opt-out por segmento da validação de navegação instantânea, força render a cada request.

Code Examples

// layout.tsx | page.tsx
import type { Viewport } from 'next'

export const viewport: Viewport = {
  themeColor: 'black',
}
  • O que demonstra: forma estática, preferida quando o viewport não depende de request.
// app/layout.tsx - viewport dependente de dado externo cacheável
export async function generateViewport() {
  'use cache'
  const { width, initialScale } = await db.query('viewport-size')
  return { width, initialScale }
}
  • O que demonstra: usar use cache quando o viewport depende de dado externo mas não de runtime data.
// app/layout.tsx - viewport com runtime data, envolto em Suspense
import { Suspense } from 'react'
import { cookies } from 'next/headers'

export async function generateViewport() {
  const cookieJar = await cookies()
  return { themeColor: cookieJar.get('theme-color')?.value }
}

export default function RootLayout({ children }) {
  return (
    <Suspense>
      <html>
        <body>{children}</body>
      </html>
    </Suspense>
  )
}
  • O que demonstra: quando o viewport precisa de dado de request (cookies), envolver <body> em Suspense pra sinalizar que a rota inteira é dinâmica.

Reference Tables

VersionChanges
v14.0.0viewport e generateViewport introduzidos

Anti-patterns

  • Usar generateViewport quando não há dependência de request: prefira o objeto estático viewport, mais simples e sem custo de render dinâmico.
  • Exportar viewport e generateViewport juntos: erro, escolha um.

Key Takeaways

  1. Viewport nunca é streamed, diferente de metadata.
  2. Com Cache Components, use cache captura o viewport no shell estático quando não depende de runtime data.
  3. Use instant = false só no segmento que realmente precisa, para não invalidar a validação estática de descendentes.
  4. Use múltiplos root layouts para isolar viewport totalmente dinâmico a rotas específicas.

Connects To

  • Metadata Files: API irmã para outras tags de <head>.
  • cacheComponents: flag que muda o comportamento de generateViewport em relação a runtime data.