diff --git a/docs/advanced-features/custom-document.md b/docs/advanced-features/custom-document.md index b6af8d8b18b1e..843f5db272c87 100644 --- a/docs/advanced-features/custom-document.md +++ b/docs/advanced-features/custom-document.md @@ -4,76 +4,67 @@ description: Extend the default document markup added by Next.js. # Custom `Document` -A custom `Document` is commonly used to augment your application's `` and `` tags. This is necessary because Next.js pages skip the definition of the surrounding document's markup. +A custom `Document` can update the `` and `` tags used to render a [Page](/docs/basic-features/pages.md). This file is only rendered on the server, so event handlers like `onClick` cannot be used in `_document`. -To override the default `Document`, create the file `./pages/_document.js` and extend the `Document` class as shown below: +To override the default `Document`, create the file `pages/_document.js` as shown below: ```jsx -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 ( - - - -
- - - - ) - } +import { Html, Head, Main, NextScript } from 'next/document' + +export default function Document() { + return ( + + + +
+ + + + ) } - -export default MyDocument ``` -> The code above is the default `Document` added by Next.js. Feel free to remove the `getInitialProps` or `render` function from `MyDocument` if you don't need to change them. - -``, ``, `
` and `` are required for the page to be properly rendered. - -Custom attributes are allowed as props, like `lang`: +The code above is the default `Document` added by Next.js. Custom attributes are allowed as props. For example, we might want to add `lang="en"` to the `` tag: ```jsx ``` -The `` component used here is not the same one from [`next/head`](/docs/api-reference/next/head.md). The `` component used here should only be used for any `` code that is common for all pages. For all other cases, such as `` tags, we recommend using [`next/head`](/docs/api-reference/next/head.md) in your pages or components. +Or add a `className` to the `body` tag: -The `ctx` object is equivalent to the one received in [`getInitialProps`](/docs/api-reference/data-fetching/get-initial-props.md#context-object), with one addition: +```jsx +<body className="bg-white"> +``` -- `renderPage`: `Function` - a callback that runs the actual React rendering logic (synchronously). It's useful to decorate this function in order to support server-rendering wrappers like Aphrodite's [`renderStatic`](https://github.com/Khan/aphrodite#server-side-rendering) +`<Html>`, `<Head />`, `<Main />` and `<NextScript />` are required for the page to be properly rendered. ## 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 or custom CSS (like `styled-jsx`). If you need shared components in all your pages (like a menu or a toolbar), take a look at the [`App`](/docs/advanced-features/custom-app.md) component instead. -- `Document`'s `getInitialProps` function is not called during client-side transitions, nor when a page is [statically optimized](/docs/advanced-features/automatic-static-optimization.md). +- The `<Head />` component used in `_document` is not the same as [`next/head`](/docs/api-reference/next/head.md). The `<Head />` component used here should only be used for any `<head>` code that is common for all pages. For all other cases, such as `<title>` tags, we recommend using [`next/head`](/docs/api-reference/next/head.md) in your pages or components. +- React components outside of `<Main />` will not be initialized by the browser. Do _not_ add application logic here or custom CSS (like `styled-jsx`). If you need shared components in all your pages (like a menu or a toolbar), read [Layouts](/docs/basic-features/layouts.md) intead. - `Document` currently does not support Next.js [Data Fetching methods](/docs/basic-features/data-fetching/overview.md) like [`getStaticProps`](/docs/basic-features/data-fetching/get-static-props.md) or [`getServerSideProps`](/docs/basic-features/data-fetching/get-server-side-props.md). ## 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. +> **Note:** This is advanced and only needed for libraries like CSS-in-JS to support server-side rendering. This is not needed for built-in `styled-jsx` support. -It takes as argument an options object for further customization: +To prepare for [React 18](/docs/advanced-features/react-18.md), we recommend avoiding customizing `getInitiaProps` and `renderPage`, if possible. + +The `ctx` object shown below is equivalent to the one received in [`getInitialProps`](/docs/api-reference/data-fetching/get-initial-props.md#context-object), with the addition of `renderPage`. ```jsx -import Document from 'next/document' +import Document, { Html, Head, Main, NextScript } from 'next/document' class MyDocument extends Document { static async getInitialProps(ctx) { const originalRenderPage = ctx.renderPage + // Run the React rendering logic synchronously ctx.renderPage = () => originalRenderPage({ - // useful for wrapping the whole react tree + // Useful for wrapping the whole react tree enhanceApp: (App) => App, - // useful for wrapping in a per-page basis + // Useful for wrapping in a per-page basis enhanceComponent: (Component) => Component, }) @@ -82,11 +73,25 @@ class MyDocument extends Document { return initialProps } + + render() { + return ( + <Html> + <Head /> + <body> + <Main /> + <NextScript /> + </body> + </Html> + ) + } } export default MyDocument ``` +> **Note**: `getInitialProps` in `_document` is not called during client-side transitions. + ## TypeScript You can use the built-in `DocumentContext` type and change the file name to `./pages/_document.tsx` like so: