Next.js: Custom Document component

Created on 14 Nov 2016  ยท  6Comments  ยท  Source: vercel/next.js

To override the default document rendering, define _document.js.
This will allow you to use any css modules and head manage components.
For example, you'd be able to replace next/css with khan/aphrodite like the following:

import React from 'react'
import Head from 'next/head'
import { StyleSheetServer } from 'aphrodite'

export default class Document extends React.Component {
  static getInitialProps ({ renderPageToString }) {
    const { html, css } = StyleSheetServer.renderStatic(() => {
      return renderPageToString()
    })
    const head = Head.rewind()
    return { html, css, head }
  }

  render () {
    return <html>
      <head>
        {this.props.head}
        <style dangerouslySetInnerHTML={{ __html: this.props.css.content }} />
      </head>
      <body>
        <div id='__next' dangerouslySetInnerHTML={{ __html: this.props.html }} />
        <script src="/next.js" />
        <script src="/static/aphrodite.js" />
        <script dangerouslySetInnerHTML={{ __html: `
          StyleSheet.rehydrate(${JSON.stringify(this.props.css.renderedClassNames)})
        `}}>
      </body>
    </html>
  }
}

Related: https://github.com/zeit/next.js/issues/247

cc @rauchg

Most helpful comment

Another reason to have a custom core document is if we want to add a className to the body tag, which is currently not possible.

A lot of bootstrap templates have classnames on this tag.

All 6 comments

This will also allow to flawlessly include external dependencies required in #221. However, it may introduce some issues with Next.js upgrades as those who chose to override the Document will need to keep track of the changes done in the Next.js built-in Document implementation.

@frol yeah, I did think about the upgrade scenario. But at the end of the day, this is advanced behavior. Most people are not going to need to extend the core document

@nkzawa also, to clarify, I was thinking pages/_document.js

Another reason to have a custom core document is if we want to add a className to the body tag, which is currently not possible.

A lot of bootstrap templates have classnames on this tag.

Totally! I second @jonaswindey point here. Even ignoring 3rd party CSS libs like bootstrap, avoiding the "white flash on load" when you have a dominant background color is important.

Stats from current PR


Default Server Mode



General

| | zeit/next.js canary | zeit/next.js canary | Change |
| - | - | - | - |
| buildDuration | 16.7s | 17.1s | โš ๏ธ +356ms |
| nodeModulesSize | 48.2 MB | 48.2 MB | โœ“ |


Client Bundles (main, webpack, commons)

| | zeit/next.js canary | zeit/next.js canary | Change |
| - | - | - | - |
| main-HASH.js | 18.1 kB | 18.1 kB | โœ“ |
| main-HASH.js gzip | 6.6 kB | 6.6 kB | โœ“ |
| webpack-HASH.js | 1.53 kB | 1.53 kB | โœ“ |
| webpack-HASH.js gzip | 746 B | 746 B | โœ“ |
| 4952ddcd88e7..2b8407376.js | 21.9 kB | 21.9 kB | โœ“ |
| 4952ddcd88e7..7376.js gzip | 7.81 kB | 7.81 kB | โœ“ |
| de003c3a9d30..2ca0edb75.js | 43.2 kB | 43.2 kB | โœ“ |
| de003c3a9d30..db75.js gzip | 15.5 kB | 15.5 kB | โœ“ |
| framework.5b..dbaff70d3.js | 125 kB | 125 kB | โœ“ |
| framework.5b..70d3.js gzip | 39.4 kB | 39.4 kB | โœ“ |
| Overall change | 210 kB | 210 kB | โœ“ |


Client Bundles (main, webpack, commons) Modern

| | zeit/next.js canary | zeit/next.js canary | Change |
| - | - | - | - |
| main-HASH.module.js | 16.4 kB | 16.4 kB | โœ“ |
| main-HASH.module.js gzip | 6.35 kB | 6.35 kB | โœ“ |
| webpack-HASH.module.js | 1.53 kB | 1.53 kB | โœ“ |
| webpack-HASH..dule.js gzip | 746 B | 746 B | โœ“ |
| de003c3a9d30..c0.module.js | 45.6 kB | 45.6 kB | โœ“ |
| de003c3a9d30..dule.js gzip | 16.5 kB | 16.5 kB | โœ“ |
| framework.5b..d3.module.js | 125 kB | 125 kB | โœ“ |
| framework.5b..dule.js gzip | 39.4 kB | 39.4 kB | โœ“ |
| Overall change | 189 kB | 189 kB | โœ“ |


Client Pages

| | zeit/next.js canary | zeit/next.js canary | Change |
| - | - | - | - |
| _app.js | 1.81 kB | 1.81 kB | โœ“ |
| _app.js gzip | 873 B | 873 B | โœ“ |
| _error.js | 12 kB | 12 kB | โœ“ |
| _error.js gzip | 4.73 kB | 4.73 kB | โœ“ |
| hooks.js | 12.7 kB | 12.7 kB | โœ“ |
| hooks.js gzip | 4.79 kB | 4.79 kB | โœ“ |
| index.js | 318 B | 318 B | โœ“ |
| index.js gzip | 222 B | 222 B | โœ“ |
| link.js | 8.14 kB | 8.14 kB | โœ“ |
| link.js gzip | 3.5 kB | 3.5 kB | โœ“ |
| routerDirect.js | 408 B | 408 B | โœ“ |
| routerDirect.js gzip | 281 B | 281 B | โœ“ |
| withRouter.js | 419 B | 419 B | โœ“ |
| withRouter.js gzip | 280 B | 280 B | โœ“ |
| Overall change | 35.8 kB | 35.8 kB | โœ“ |


Client Pages Modern

| | zeit/next.js canary | zeit/next.js canary | Change |
| - | - | - | - |
| _app.module.js | 1.7 kB | 1.7 kB | โœ“ |
| _app.module.js gzip | 832 B | 832 B | โœ“ |
| _error.module.js | 23.3 kB | 23.3 kB | โœ“ |
| _error.module.js gzip | 8.59 kB | 8.59 kB | โœ“ |
| hooks.module.js | 1.52 kB | 1.52 kB | โœ“ |
| hooks.module.js gzip | 793 B | 793 B | โœ“ |
| index.module.js | 294 B | 294 B | โœ“ |
| index.module.js gzip | 223 B | 223 B | โœ“ |
| link.module.js | 8.53 kB | 8.53 kB | โœ“ |
| link.module.js gzip | 3.68 kB | 3.68 kB | โœ“ |
| routerDirect.module.js | 394 B | 394 B | โœ“ |
| routerDirect..dule.js gzip | 281 B | 281 B | โœ“ |
| withRouter.module.js | 404 B | 404 B | โœ“ |
| withRouter.m..dule.js gzip | 278 B | 278 B | โœ“ |
| Overall change | 36.1 kB | 36.1 kB | โœ“ |


Client Build Manifests

| | zeit/next.js canary | zeit/next.js canary | Change |
| - | - | - | - |
| _buildManifest.js | 81 B | 81 B | โœ“ |
| _buildManifest.js gzip | 61 B | 61 B | โœ“ |
| _buildManifest.module.js | 81 B | 81 B | โœ“ |
| _buildManife..dule.js gzip | 61 B | 61 B | โœ“ |
| Overall change | 162 B | 162 B | โœ“ |


Rendered Page Sizes

| | zeit/next.js canary | zeit/next.js canary | Change |
| - | - | - | - |
| index.html | 3.62 kB | 3.62 kB | โœ“ |
| index.html gzip | 946 B | 946 B | โœ“ |
| link.html | 3.66 kB | 3.66 kB | โœ“ |
| link.html gzip | 954 B | 954 B | โœ“ |
| withRouter.html | 3.67 kB | 3.67 kB | โœ“ |
| withRouter.html gzip | 941 B | 941 B | โœ“ |
| Overall change | 10.9 kB | 10.9 kB | โœ“ |





Serverless Mode



General

| | zeit/next.js canary | zeit/next.js canary | Change |
| - | - | - | - |
| buildDuration | 17s | 16.8s | -253ms |
| nodeModulesSize | 48.2 MB | 48.2 MB | โœ“ |


Client Bundles (main, webpack, commons)

| | zeit/next.js canary | zeit/next.js canary | Change |
| - | - | - | - |
| main-HASH.js | 18.1 kB | 18.1 kB | โœ“ |
| main-HASH.js gzip | 6.6 kB | 6.6 kB | โœ“ |
| webpack-HASH.js | 1.53 kB | 1.53 kB | โœ“ |
| webpack-HASH.js gzip | 746 B | 746 B | โœ“ |
| 4952ddcd88e7..2b8407376.js | 21.9 kB | 21.9 kB | โœ“ |
| 4952ddcd88e7..7376.js gzip | 7.81 kB | 7.81 kB | โœ“ |
| de003c3a9d30..2ca0edb75.js | 43.2 kB | 43.2 kB | โœ“ |
| de003c3a9d30..db75.js gzip | 15.5 kB | 15.5 kB | โœ“ |
| framework.5b..dbaff70d3.js | 125 kB | 125 kB | โœ“ |
| framework.5b..70d3.js gzip | 39.4 kB | 39.4 kB | โœ“ |
| Overall change | 210 kB | 210 kB | โœ“ |


Client Bundles (main, webpack, commons) Modern

| | zeit/next.js canary | zeit/next.js canary | Change |
| - | - | - | - |
| main-HASH.module.js | 16.4 kB | 16.4 kB | โœ“ |
| main-HASH.module.js gzip | 6.35 kB | 6.35 kB | โœ“ |
| webpack-HASH.module.js | 1.53 kB | 1.53 kB | โœ“ |
| webpack-HASH..dule.js gzip | 746 B | 746 B | โœ“ |
| de003c3a9d30..c0.module.js | 45.6 kB | 45.6 kB | โœ“ |
| de003c3a9d30..dule.js gzip | 16.5 kB | 16.5 kB | โœ“ |
| framework.5b..d3.module.js | 125 kB | 125 kB | โœ“ |
| framework.5b..dule.js gzip | 39.4 kB | 39.4 kB | โœ“ |
| Overall change | 189 kB | 189 kB | โœ“ |


Client Pages

| | zeit/next.js canary | zeit/next.js canary | Change |
| - | - | - | - |
| _app.js | 1.81 kB | 1.81 kB | โœ“ |
| _app.js gzip | 873 B | 873 B | โœ“ |
| _error.js | 12 kB | 12 kB | โœ“ |
| _error.js gzip | 4.73 kB | 4.73 kB | โœ“ |
| hooks.js | 12.7 kB | 12.7 kB | โœ“ |
| hooks.js gzip | 4.79 kB | 4.79 kB | โœ“ |
| index.js | 318 B | 318 B | โœ“ |
| index.js gzip | 222 B | 222 B | โœ“ |
| link.js | 8.14 kB | 8.14 kB | โœ“ |
| link.js gzip | 3.5 kB | 3.5 kB | โœ“ |
| routerDirect.js | 408 B | 408 B | โœ“ |
| routerDirect.js gzip | 281 B | 281 B | โœ“ |
| withRouter.js | 419 B | 419 B | โœ“ |
| withRouter.js gzip | 280 B | 280 B | โœ“ |
| Overall change | 35.8 kB | 35.8 kB | โœ“ |


Client Pages Modern

| | zeit/next.js canary | zeit/next.js canary | Change |
| - | - | - | - |
| _app.module.js | 1.7 kB | 1.7 kB | โœ“ |
| _app.module.js gzip | 832 B | 832 B | โœ“ |
| _error.module.js | 23.3 kB | 23.3 kB | โœ“ |
| _error.module.js gzip | 8.59 kB | 8.59 kB | โœ“ |
| hooks.module.js | 1.52 kB | 1.52 kB | โœ“ |
| hooks.module.js gzip | 793 B | 793 B | โœ“ |
| index.module.js | 294 B | 294 B | โœ“ |
| index.module.js gzip | 223 B | 223 B | โœ“ |
| link.module.js | 8.53 kB | 8.53 kB | โœ“ |
| link.module.js gzip | 3.68 kB | 3.68 kB | โœ“ |
| routerDirect.module.js | 394 B | 394 B | โœ“ |
| routerDirect..dule.js gzip | 281 B | 281 B | โœ“ |
| withRouter.module.js | 404 B | 404 B | โœ“ |
| withRouter.m..dule.js gzip | 278 B | 278 B | โœ“ |
| Overall change | 36.1 kB | 36.1 kB | โœ“ |


Client Build Manifests

| | zeit/next.js canary | zeit/next.js canary | Change |
| - | - | - | - |
| _buildManifest.js | 81 B | 81 B | โœ“ |
| _buildManifest.js gzip | 61 B | 61 B | โœ“ |
| _buildManifest.module.js | 81 B | 81 B | โœ“ |
| _buildManife..dule.js gzip | 61 B | 61 B | โœ“ |
| Overall change | 162 B | 162 B | โœ“ |


Serverless bundles

| | zeit/next.js canary | zeit/next.js canary | Change |
| - | - | - | - |
| _error.js | 253 kB | 253 kB | โœ“ |
| _error.js gzip | 67.9 kB | 67.9 kB | โœ“ |
| hooks.html | 3.75 kB | 3.75 kB | โœ“ |
| hooks.html gzip | 979 B | 979 B | โœ“ |
| index.js | 254 kB | 254 kB | โœ“ |
| index.js gzip | 68.2 kB | 68.2 kB | โœ“ |
| link.js | 261 kB | 261 kB | โœ“ |
| link.js gzip | 70.2 kB | 70.2 kB | โœ“ |
| routerDirect.js | 255 kB | 255 kB | โœ“ |
| routerDirect.js gzip | 68.3 kB | 68.3 kB | โœ“ |
| withRouter.js | 255 kB | 255 kB | โœ“ |
| withRouter.js gzip | 68.3 kB | 68.3 kB | โœ“ |
| Overall change | 1.28 MB | 1.28 MB | โœ“ |

Commit: 0bcd1fc39bb07f67b94238a0e867e9c3fe73a163

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jesselee34 picture jesselee34  ยท  3Comments

ghost picture ghost  ยท  3Comments

timneutkens picture timneutkens  ยท  3Comments

DvirSh picture DvirSh  ยท  3Comments

havefive picture havefive  ยท  3Comments