跳至内容

自定义文档

自定义的Document可以更新用于渲染页面<html><body>标签。

要覆盖默认的Document,请创建文件pages/_document,如下所示

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

了解一下:

  • _document仅在服务器端渲染,因此此文件中无法使用诸如onClick之类的事件处理程序。
  • <Html><Head /><Main /><NextScript />是页面正确渲染所必需的。

注意事项

  • _document中使用的<Head />组件与next/head不同。此处使用的<Head />组件仅应用于所有页面通用的任何<head>代码。对于所有其他情况,例如<title>标签,我们建议在您的页面或组件中使用next/head
  • <Main />之外的 React 组件不会由浏览器初始化。请不要在此处添加应用程序逻辑或自定义 CSS(如styled-jsx)。如果您需要在所有页面中共享组件(如菜单或工具栏),请改为阅读布局
  • Document目前不支持 Next.js 的数据获取方法,例如getStaticPropsgetServerSideProps

自定义renderPage

自定义renderPage是高级操作,仅在 CSS-in-JS 等库需要支持服务器端渲染时才需要。对于内置的styled-jsx支持,不需要这样做。

我们不建议使用此模式。 相反,请考虑逐步采用App Router,它允许您更轻松地为页面和布局获取数据。

pages/_document.tsx
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
 
    // Run the React rendering logic synchronously
    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
  }
 
  render() {
    return (
      <Html lang="en">
        <Head />
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    )
  }
}
 
export default MyDocument

了解一下:

  • _document中的getInitialProps在客户端转换期间不会被调用。
  • _documentctx对象等效于在getInitialProps中接收到的对象,并增加了renderPage