Next.js の _document.tsx とは何か
概要
_document.tsx は Next.js におけるHTMLドキュメント全体の構造を定義するファイルです。
通常のReactプロジェクトにある index.html(<html> や <body> タグを含むファイル)に相当する役割を担います。
コード全体
import { Html, Head, Main, NextScript } from "next/document";
export default function Document() {
return (
<Html lang="en">
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
各行の解説
コンポーネントのインポート
import { Html, Head, Main, NextScript } from "next/document";
Next.js が提供する4つの専用コンポーネントをインポートしています。
これらはページを正しくレンダリングするためにすべて必須です。
| コンポーネント | 役割 |
|---|---|
Html |
<html> タグに対応。lang 属性などを設定できる |
Head |
<head> タグに対応。全ページ共通のメタ情報やフォント読み込みを記述する |
Main |
ページ本体がレンダリングされる場所(_app.tsx の出力がここに入る) |
NextScript |
Next.js が動作するために必要なスクリプトを挿入する |
Document コンポーネント本体
export default function Document() {
return (
<Html lang="en">
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
この構造は、通常のHTMLファイルの骨格と対応しています。
<Html> → <html>
<Head /> → <head>...</head>
<body> → <body>
<Main /> → ページの中身
<NextScript /> → Next.js のスクリプト群
</body> → </body>
</Html> → </html>
_app.tsx との違い
_document.tsx と _app.tsx は似ているようで、役割が明確に異なります。
| 比較項目 | _document.tsx |
_app.tsx |
|---|---|---|
| 担当範囲 | HTMLドキュメント全体(<html>, <head>, <body>) |
ページコンポーネントの初期化 |
| 実行環境 | サーバーサイドのみ | サーバーサイド+クライアントサイド |
| イベントハンドラ |
onClick などは使えない
|
使える |
| グローバルCSS | インポートできない | インポートできる(唯一の場所) |
| 状態管理 | できない | Context Provider などを設置できる |
処理の流れにおける位置づけ
ユーザーがページにアクセス
↓
_document.tsx が HTML の骨格を生成(サーバーサイド)
↓
_app.tsx が Component(ページ)を初期化
↓
該当ページのコンポーネントがレンダリング
↓
完成した HTML がブラウザに送信される
なぜ _document.tsx が必要なのか
通常の React プロジェクトでは public/index.html に <html> や <body> タグを直接書きます。
しかし Next.js には index.html が存在しません。
Next.js はこの HTML の骨格をフレームワーク内部で自動生成していますが、
それをカスタマイズしたい場合に _document.tsx を使います。
つまり、_document.tsx は Next.js が隠している index.html を上書き(オーバーライド)するためのファイルです。
Head(next/document)と Head(next/head)の違い
Next.js には2つの Head コンポーネントがあるため、混同しやすいポイントです。
| 項目 |
next/document の Head
|
next/head の Head
|
|---|---|---|
| 使う場所 |
_document.tsx のみ |
各ページコンポーネント内 |
| 用途 |
全ページ共通の <head> 内容 |
ページごとの <head> 内容 |
| 使用例 | Webフォントの読み込み、共通メタタグ | ページ固有の <title>、OGP設定 |
// _document.tsx 内(全ページ共通)
<Head>
<link
href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP&display=swap"
rel="stylesheet"
/>
</Head>
// pages/about.tsx 内(このページだけ)
import Head from "next/head";
export default function About() {
return (
<>
<Head>
<title>About | MySite</title>
<meta name="description" content="About ページの説明" />
</Head>
<h1>About</h1>
</>
);
}
_document.tsx の代表的な使い方
デフォルトの状態は最小構成です。実際のプロジェクトでは以下のようなカスタマイズを行います。
import { Html, Head, Main, NextScript } from "next/document";
export default function Document() {
return (
<Html lang="ja">
<Head>
{/* Google Fonts の読み込み */}
<link
href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP&display=swap"
rel="stylesheet"
/>
{/* ファビコンの設定 */}
<link rel="icon" href="/favicon.ico" />
{/* 全ページ共通のメタタグ */}
<meta name="theme-color" content="#ffffff" />
</Head>
<body className="antialiased">
{/* ダークモード用のフラッシュ防止スクリプト */}
<script dangerouslySetInnerHTML={{ __html: `/* theme script */` }} />
<Main />
<NextScript />
</body>
</Html>
);
}
| 用途 | 概要 |
|---|---|
lang 属性の設定 |
<Html lang="ja"> でページの言語を指定 |
| Webフォントの読み込み | Google Fonts などの外部フォントを全ページに適用 |
| ファビコンの設定 | サイトのアイコンを指定 |
| 共通メタタグ |
theme-color や charset など全ページに必要なメタ情報 |
body へのクラス付与 |
Tailwind CSS の antialiased など |
| 初期化スクリプトの挿入 | ダークモードのちらつき防止など、レンダリング前に実行したいスクリプト |
注意点
-
_document.tsxはサーバーサイドでのみレンダリングされる。onClickなどのイベントハンドラは動作しない -
<Html>,<Head />,<Main />,<NextScript />の4つは削除してはいけない(ページが正しくレンダリングされなくなる) - アプリケーションのロジックや
styled-jsxなどの CSS-in-JS は_document.tsxに書かず、_app.tsxに書く - グローバル CSS のインポートは
_document.tsxではなく_app.tsxで行う
まとめ
-
_document.tsxは Next.js が隠している HTML の骨格(<html>,<head>,<body>)をカスタマイズするファイル - サーバーサイドでのみ実行され、クライアントサイドのイベントは使えない
-
_app.tsxが「ページの初期化」を担当するのに対し、_document.tsxは「HTMLドキュメントの構造」を担当する -
next/documentのHeadとnext/headのHeadは別物なので注意