Documento personalizado

Un Document personalizado puede actualizar las etiquetas <html> y <body> utilizadas para renderizar una Página.

Para sobrescribir el Document predeterminado, crea el archivo pages/_document como se muestra a continuación:

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

export default function Document() {
  return (
    <Html lang="en">
      <Head />
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  )
}
import { Html, Head, Main, NextScript } from 'next/document'

export default function Document() {
  return (
    <Html lang="en">
      <Head />
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  )
}

Nota importante

  • _document solo se renderiza en el servidor, por lo que no se pueden usar manejadores de eventos como onClick en este archivo.
  • <Html>, <Head />, <Main /> y <NextScript /> son necesarios para que la página se renderice correctamente.

Consideraciones

  • El componente <Head /> usado en _document no es el mismo que next/head. El <Head /> usado aquí solo debe contener código <head> común a todas las páginas. Para otros casos, como etiquetas <title>, se recomienda usar next/head en tus páginas o componentes.
  • Los componentes de React fuera de <Main /> no serán inicializados por el navegador. No añadas lógica de aplicación aquí ni CSS personalizado (como styled-jsx). Si necesitas componentes compartidos en todas tus páginas (como un menú o barra de herramientas), consulta Layouts.
  • Document actualmente no soporta los métodos de obtención de datos de Next.js como getStaticProps o getServerSideProps.

Personalizando renderPage

Personalizar renderPage es avanzado y solo necesario para bibliotecas como CSS-in-JS que requieren renderizado del lado del servidor (SSR). No es necesario para el soporte nativo de styled-jsx.

No recomendamos este patrón. En su lugar, considera adoptar gradualmente el App Router, que permite obtener datos más fácilmente para páginas y layouts.

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

class MyDocument extends Document {
  static async getInitialProps(
    ctx: DocumentContext
  ): Promise<DocumentInitialProps> {
    const originalRenderPage = ctx.renderPage

    // Ejecuta la lógica de renderizado de React sincrónicamente
    ctx.renderPage = () =>
      originalRenderPage({
        // Útil para envolver todo el árbol de React
        enhanceApp: (App) => App,
        // Útil para envolver por página
        enhanceComponent: (Component) => Component,
      })

    // Ejecuta el `getInitialProps` padre, que ahora incluye el `renderPage` personalizado
    const initialProps = await Document.getInitialProps(ctx)

    return initialProps
  }

  render() {
    return (
      <Html lang="en">
        <Head />
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    )
  }
}

export default MyDocument
import Document, { Html, Head, Main, NextScript } from 'next/document'

class MyDocument extends Document {
  static async getInitialProps(ctx) {
    const originalRenderPage = ctx.renderPage

    // Ejecuta la lógica de renderizado de React sincrónicamente
    ctx.renderPage = () =>
      originalRenderPage({
        // Útil para envolver todo el árbol de React
        enhanceApp: (App) => App,
        // Útil para envolver por página
        enhanceComponent: (Component) => Component,
      })

    // Ejecuta el `getInitialProps` padre, que ahora incluye el `renderPage` personalizado
    const initialProps = await Document.getInitialProps(ctx)

    return initialProps
  }

  render() {
    return (
      <Html lang="en">
        <Head />
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    )
  }
}

export default MyDocument

Nota importante

  • getInitialProps en _document no se llama durante transiciones del lado del cliente.
  • El objeto ctx para _document es equivalente al recibido en getInitialProps, con la adición de renderPage.