Skip to content

Latest commit

 

History

History
84 lines (61 loc) · 3.33 KB

custom-document.md

File metadata and controls

84 lines (61 loc) · 3.33 KB
description
Extend the default document markup added by Next.js.

Custom Document

A custom Document is commonly used to augment your application's <html> and <body> tags. This is necessary because Next.js pages skip the definition of the surrounding document's markup.

A custom Document can also include getInitialProps for expressing asynchronous server-rendering data requirements.

To override the default Document, create the file ./pages/_document.js and extend the Document class as shown below:

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

class MyDocument extends Document {
  static async getInitialProps(ctx) {
    const initialProps = await Document.getInitialProps(ctx)
    return { ...initialProps }
  }

  render() {
    return (
      <Html>
        <Head />
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    )
  }
}

export default MyDocument

<Html>, <Head />, <Main /> and <NextScript /> are required for the page to be properly rendered. Custom attributes are allowed as props, like lang:

<Html lang="en">

The ctx object is equivalent to the one received in getInitialProps, with one addition:

  • renderPage: Function - a callback that executes the actual React rendering logic (synchronously). It's useful to decorate this function in order to support server-rendering wrappers like Aphrodite's renderStatic

Caveats

  • Document is only rendered in the server, event handlers like onClick won't work
  • React components outside of <Main /> will not be initialized by the browser. Do not add application logic here. If you need shared components in all your pages (like a menu or a toolbar), take a look at the App component instead
  • Document's getInitialProps function is not called during client-side transitions, nor when a page is statically optimized
  • Make sure to check if ctx.req / ctx.res are defined in getInitialProps. Those variables will be undefined when a page is being statically exported by Automatic Static Optimization or by next export

Customizing renderPage

It should be noted that the only reason you should be customizing renderPage is for usage with css-in-js libraries that need to wrap the application to properly work with server-side rendering.

It takes as argument an options object for further customization:

import Document from 'next/document'

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

    ctx.renderPage = () =>
      originalRenderPage({
        // useful for wrapping the whole react tree
        enhanceApp: App => App,
        // useful for wrapping in a per-page basis
        enhanceComponent: Component => Component,
      })

    // Run the parent `getInitialProps`, it now includes the custom `renderPage`
    const initialProps = await Document.getInitialProps(ctx)

    return initialProps
  }
}

export default MyDocument