跳到主要内容

自定义 Document

自定义 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 路由,它可以让你更轻松地为页面和布局获取数据。

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

// 同步运行 React 渲染逻辑
ctx.renderPage = () =>
originalRenderPage({
// 用于包裹整个 React 树
enhanceApp: (App) => App,
// 用于按页面基础进行包裹
enhanceComponent: (Component) => Component,
})

// 运行父级 `getInitialProps`,现在它包含自定义的 `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