Capítulo 346 de 456

Custom Document

Core Idea

pages/_document.js sobrescreve a marcação <html> e <body> compartilhada por todas as páginas do Pages Router; renderiza só no servidor.

Key Concepts

  • pages/_document: exporta um componente Document usando Html, Head, Main, NextScript de next/document.
  • Html, Head, Main, NextScript: componentes obrigatórios para a página renderizar corretamente; Head aqui é diferente de next/head (usar next/head para <title> por página).
  • renderPage customizado: hook avançado em getInitialProps do Document, usado por libs CSS-in-JS para SSR (não recomendado; App Router é preferido).

Code Examples

import { Html, Head, Main, NextScript } from 'next/document'

export default function Document() {
  return (
    <Html lang="en">
      <Head />
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  )
}
  • O que demonstra: override mínimo padrão do Document.
class MyDocument extends Document {
  static async getInitialProps(ctx: DocumentContext): Promise<DocumentInitialProps> {
    const originalRenderPage = ctx.renderPage
    ctx.renderPage = () =>
      originalRenderPage({
        enhanceApp: (App) => App,
        enhanceComponent: (Component) => Component,
      })
    const initialProps = await Document.getInitialProps(ctx)
    return initialProps
  }
  render() {
    return (
      <Html lang="en">
        <Head />
        <body><Main /><NextScript /></body>
      </Html>
    )
  }
}
  • O que demonstra: customização de renderPage para wrappear a árvore React inteira (uso avançado, ex. CSS-in-JS SSR).

Anti-patterns

  • Lógica de aplicação ou CSS custom fora de <Main />: componentes React fora de <Main /> não são inicializados pelo browser; nada de onClick ou styled-jsx ali.
  • Usar <Head /> do _document para <title> por página: essa Head é só para código <head> comum a todas as páginas; usar next/head para tags por página.
  • Document não suporta getStaticProps/getServerSideProps.

Key Takeaways

  1. _document roda só no servidor; nenhum event handler funciona nele.
  2. getInitialProps em _document não é chamado em transições client-side.
  3. Customizar renderPage é avançado e desnecessário para styled-jsx (já suportado nativamente).

Connects To

  • custom-app: _app cuida da inicialização de páginas; _document do HTML/body ao redor.
  • pages-and-layouts: para layout compartilhado, usar o padrão de Layout, não o Document.