* Mention <title> and styled-jsx caveats * Update custom-document.md Co-authored-by: Tim Neutkens <tim@timneutkens.nl>
3.5 KiB
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'srenderStatic
Caveats
Document
is only rendered in the server, event handlers likeonClick
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 theApp
component instead Document
'sgetInitialProps
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 ingetInitialProps
. Those variables will beundefined
when a page is being statically exported by Automatic Static Optimization or bynext export
- Common errors include adding a
<title>
in the<Head />
tag or usingstyled-jsx
. These should be avoided inpages/_document.js
as they lead to unexpected behavior
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