# 画面設計書 2-ドキュメント (_document)

## 概要

Pages RouterにおけるHTMLドキュメントの基本構造（html, head, body）を定義するサーバーサイドレンダリング用テンプレートの設計書。CSS、スクリプト、フォントの読み込み管理を担当する。

### 本画面の処理概要

**業務上の目的・背景**：Next.jsのPages Routerで提供される全てのページは、共通のHTMLドキュメント構造を必要とする。本コンポーネントは、`<html>`, `<head>`, `<body>`タグを含むHTML文書の骨格を定義し、CSS・JavaScript・フォントなどの静的アセットのロード戦略を管理する。サーバーサイドでのみレンダリングされ、CSSインジェクション（CSS-in-JSライブラリ等）やカスタムフォントのプリロード、スクリプトの最適化ロードなどフレームワークレベルの基盤機能を提供する。ユーザーはこのコンポーネントを拡張してカスタムDocument定義を行うことができる。

**画面へのアクセス方法**：本コンポーネントはユーザーが直接アクセスする画面ではなく、Pages Router配下の全ページレンダリング時にサーバーサイドで自動的に呼び出される。Next.jsのレンダリングパイプラインの一部として機能し、ユーザーがカスタム`_document.tsx`を作成して上書きすることも可能。

**主要な操作・処理内容**：
1. `Html`コンポーネントが`<html>`タグをレンダリングし、locale属性とdeploymentIdを設定する
2. `Head`コンポーネントがCSS・JavaScript・フォントの`<link>`タグとスクリプトタグを生成する
3. CSSファイルのpreload/stylesheet読み込みを管理する
4. 動的インポートされたチャンクのpreloadリンクを生成する
5. polyfillスクリプト、beforeInteractiveスクリプト、Partytown Workerスクリプトの読み込みを制御する
6. Next Fontマニフェストに基づくフォントのpreload/preconnectリンクを生成する
7. `Main`コンポーネントがページ本文のレンダリングターゲットを提供する
8. `NextScript`コンポーネントが`__NEXT_DATA__`のインラインJSONとページスクリプトを出力する

**画面遷移**：
- 本コンポーネントは全Pages Routerページの外枠として機能するため、特定の遷移先・遷移元は持たない
- `_app`コンポーネント、各ページコンポーネントを内包する構造となる

**権限による表示制御**：権限による表示制御は行わない。全リクエストに対して同一のドキュメント構造を提供する。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 32 | カスタムDocument | 主機能 | HTMLドキュメント構造（html, head, body）の定義とサーバーサイドレンダリング用テンプレート生成 |
| 26 | Pages Router | 補助機能 | Pages Routerのページファイル管理を通じたCSS・スクリプトの読み込み制御 |
| 34 | サーバーサイドレンダリング（SSR） | 補助機能 | サーバーサイドのみでのドキュメントレンダリング処理 |
| 60 | next/script（Script） | 補助機能 | beforeInteractive戦略のスクリプト読み込み管理 |
| 59 | next/font | 補助機能 | Next Font Manifestに基づくフォントのpreload・preconnectリンク生成 |

## 画面種別

テンプレート（HTMLドキュメント構造定義）

## URL/ルーティング

特定のURLパターンは持たない。Pages Router配下の全ページリクエストに対してサーバーサイドでレンダリングされる。

## 入出力項目

| 項目名 | 入出力 | 型 | 必須 | 説明 |
|--------|--------|------|------|------|
| __NEXT_DATA__ | 入力 | NEXT_DATA | はい | ページデータ（props, page, query, buildId等）をJSON形式で保持 |
| buildManifest | 入力 | BuildManifest | はい | ビルド成果物のマニフェスト情報（JS/CSSファイルパス） |
| dynamicImports | 入力 | string[] | はい | 動的インポートされたモジュールのファイルパス一覧 |
| assetPrefix | 入力 | string | いいえ | 静的アセットのURLプレフィックス |
| nextFontManifest | 入力 | NextFontManifest | いいえ | Next Fontのマニフェスト情報 |
| scriptLoader | 入力 | object | はい | next/scriptで登録されたスクリプトの情報 |
| nonce | 入力 | string | いいえ | Content Security Policy用のnonce値 |
| crossOrigin | 入力 | string | いいえ | CORSポリシー設定（anonymous / use-credentials） |
| styles | 入力 | ReactElement[] | いいえ | CSS-in-JSなどのインラインスタイル |
| HTML出力 | 出力 | string | はい | 完全なHTMLドキュメント文字列 |

## 表示項目

| 項目名 | 表示位置 | 説明 |
|--------|----------|------|
| CSSリンク | headタグ内 | ページ用とアプリ共通のCSSファイルへのlink要素 |
| フォントプリロード | headタグ内 | Next Fontマニフェストに基づくフォントファイルのpreloadリンク |
| スクリプトプリロード | headタグ内 | JSファイルのpreloadリンク |
| ページ本文 | bodyタグ内 | Mainコンポーネントによるページコンテンツ |
| __NEXT_DATA__ | bodyタグ内 | JSON形式のページデータ（script type=application/json） |
| ページスクリプト | bodyタグ内 | polyfill・動的チャンク・ページJSファイル |

## イベント仕様

### 1-getInitialProps

サーバーサイドレンダリング時に`getInitialProps`が呼ばれ、`renderPage`コールバックを実行してReactコンポーネントツリーのレンダリング結果（HTML文字列とhead要素）を取得する。

### 2-handleDocumentScriptLoaderItems

`Html`コンポーネントのレンダリング時に`handleDocumentScriptLoaderItems`が呼ばれ、子要素から`next/script`コンポーネントを検出してscriptLoaderに登録する。`beforeInteractive`戦略のスクリプトは`scriptLoader.beforeInteractive`に、その他は`__NEXT_DATA__.scriptLoader`に登録される。

## データベース更新仕様

### 操作別データベース影響一覧

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| なし | - | - | 本画面はデータベースへのアクセスを行わない |

### テーブル別更新項目詳細

データベース操作なし。

## メッセージ仕様

| メッセージID | 種別 | 条件 | メッセージ内容 |
|-------------|------|------|----------------|
| WARN-TITLE | 警告 | 開発環境でHead内に`<title>`を使用 | Warning: `<title>` should not be used in _document.js's `<Head>`. |
| WARN-VIEWPORT | 警告 | 開発環境でHead内にviewport metaを使用 | Warning: viewport meta tags should not be used in _document.js's `<Head>`. |
| WARN-CROSSORIGIN | 警告 | Head属性にcrossOriginを使用 | Warning: `Head` attribute `crossOrigin` is deprecated. |
| WARN-LARGE-DATA | 警告 | __NEXT_DATA__がlargePageDataBytesを超過 | Warning: data for page "{page}" is {size} which exceeds the threshold |
| ERR-CIRCULAR | エラー | __NEXT_DATA__に循環参照あり | Circular structure in "getInitialProps" result of page "{page}" |

## 例外処理

| 例外条件 | 挙動 |
|----------|------|
| PartyTownモジュール未インストール | MODULE_NOT_FOUNDエラーをキャッチし、nullを返す（正常動作として無視） |
| __NEXT_DATA__の循環参照 | JSON.stringify時にエラーをキャッチし、説明付きのErrorをスロー |
| __NEXT_DATA__サイズ超過 | 警告ログを出力するが処理は継続 |

## 備考

- サーバーサイドでのみレンダリングされる。クライアントサイドでは再レンダリングされない
- `NEXT_BUILTIN_DOCUMENT`定数で組み込みDocumentと区別するためのマーカーが設定される
- `InternalFunctionDocument`は関数コンポーネント版のビルトインDocumentとして内部的に使用される
- FOUC（Flash of Unstyled Content）防止のため、開発環境では`body{display:none}`スタイルが一時的に挿入される
- `optimizeCss`オプション有効時はCSSリンクのpreloadが省略され、最適化された順序でロードされる
- `disableOptimizedLoading`オプションでスクリプトのdefer/async戦略を切り替え可能
- トレース用メタデータ（experimentalClientTraceMetadata）がhead内にmetaタグとして出力される場合がある

---

## コードリーディングガイド

本画面を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、Documentコンポーネントで使用される型定義を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | utils.ts | `packages/next/src/shared/lib/utils.ts` | L184-196: `DocumentContext`, `DocumentInitialProps`, `DocumentProps`の型定義 |
| 1-2 | _document.tsx | `packages/next/src/pages/_document.tsx` | L32-49: `OriginProps`, `DocumentFiles`, `HeadProps`の型定義 |
| 1-3 | html-context.shared-runtime.ts | `packages/next/src/shared/lib/html-context.shared-runtime.ts` | `HtmlProps`型 - Documentのコンテキスト情報 |

**読解のコツ**: `DocumentFiles`は`sharedFiles`（_app用）、`pageFiles`（ページ用）、`allFiles`（重複排除済みの全ファイル）の3つのフィールドを持つ。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | _document.tsx | `packages/next/src/pages/_document.tsx` | L962-984: `Document`クラス - getInitialPropsとrenderメソッド |
| 2-2 | _document.tsx | `packages/next/src/pages/_document.tsx` | L988-1000: `InternalFunctionDocument` - ビルトインDocument |

**主要処理フロー**:
1. **L969-971**: `getInitialProps`で`ctx.defaultGetInitialProps`を呼び出し
2. **L973-983**: `render`メソッドで`Html > Head + body > Main + NextScript`の構造を返す

#### Step 3: Headコンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | _document.tsx | `packages/next/src/pages/_document.tsx` | L372-733: `Head`クラス - CSSリンク生成、スクリプトプリロード、フォントリンク生成 |
| 3-2 | _document.tsx | `packages/next/src/pages/_document.tsx` | L573-731: `Head.render()` - 要素の出力順序を制御 |

**主要処理フロー**:
- **L377-445**: `getCssLinks` - CSS preloadリンクとstylesheetリンクの生成
- **L447-474**: `getPreloadDynamicChunks` - 動的インポートチャンクのpreload
- **L476-507**: `getPreloadMainLinks` - メインスクリプトのpreload
- **L509-555**: `getBeforeInteractiveInlineScripts` - beforeInteractive戦略のインラインスクリプト
- **L650-654**: `getNextFontLinkTags`呼び出し - フォントpreload/preconnectリンク生成

#### Step 4: NextScriptコンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | _document.tsx | `packages/next/src/pages/_document.tsx` | L792-923: `NextScript`クラス - __NEXT_DATA__出力とスクリプト管理 |
| 4-2 | _document.tsx | `packages/next/src/pages/_document.tsx` | L813-857: `getInlineScriptSource` - JSON出力とサイズ警告 |

#### Step 5: ヘルパー関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | _document.tsx | `packages/next/src/pages/_document.tsx` | L54-66: `getDocumentFiles` - ビルドマニフェストからファイル一覧取得 |
| 5-2 | _document.tsx | `packages/next/src/pages/_document.tsx` | L68-95: `getPolyfillScripts` - Polyfillスクリプト生成 |
| 5-3 | _document.tsx | `packages/next/src/pages/_document.tsx` | L311-364: `getNextFontLinkTags` - フォントリンクタグ生成 |
| 5-4 | _document.tsx | `packages/next/src/pages/_document.tsx` | L735-790: `handleDocumentScriptLoaderItems` - script loaderアイテム処理 |

### プログラム呼び出し階層図

```
Next.js SSRパイプライン
    |
    +-- Document.getInitialProps(ctx)
    |       +-- ctx.defaultGetInitialProps(ctx)
    |
    +-- Document.render()
            |
            +-- Html コンポーネント
            |       +-- handleDocumentScriptLoaderItems()
            |       +-- useHtmlContext()
            |
            +-- Head コンポーネント
            |       +-- getDocumentFiles()
            |       +-- getCssLinks()
            |       +-- getPreloadDynamicChunks()
            |       +-- getPreloadMainLinks()
            |       +-- getBeforeInteractiveInlineScripts()
            |       +-- getPolyfillScripts()
            |       +-- getPreNextScripts()
            |       |       +-- getPreNextWorkerScripts()
            |       +-- getDynamicChunks()
            |       +-- getScripts()
            |       +-- getNextFontLinkTags()
            |
            +-- Main コンポーネント
            |       +-- <next-js-internal-body-render-target />
            |
            +-- NextScript コンポーネント
                    +-- getInlineScriptSource()
                    +-- getPolyfillScripts()
                    +-- getPreNextScripts()
                    +-- getDynamicChunks()
                    +-- getScripts()
```

### データフロー図

```
[入力]                      [処理]                          [出力]

HtmlProps (context) ----> Document.render() ----------> HTML文字列
  |                         |
  +-- buildManifest ------> getDocumentFiles() -------> DocumentFiles
  +-- dynamicImports -----> getDynamicChunks() -------> <script> タグ
  +-- nextFontManifest ---> getNextFontLinkTags() ----> <link> タグ
  +-- scriptLoader -------> getPreNextScripts() ------> <script> タグ
  +-- __NEXT_DATA__ ------> getInlineScriptSource() --> JSON script
  +-- styles -------------> Head.render() ------------> <style> タグ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| _document.tsx | `packages/next/src/pages/_document.tsx` | ソース | Documentコンポーネント本体（Html, Head, Main, NextScript） |
| utils.ts | `packages/next/src/shared/lib/utils.ts` | ソース | DocumentContext, DocumentProps等の型定義 |
| html-context.shared-runtime.ts | `packages/next/src/shared/lib/html-context.shared-runtime.ts` | ソース | HtmlContext, HtmlProps型定義 |
| get-page-files.ts | `packages/next/src/server/get-page-files.ts` | ソース | BuildManifestからページファイルを取得 |
| htmlescape.ts | `packages/next/src/server/htmlescape.ts` | ソース | JSON文字列のHTMLエスケープ処理 |
| encode-uri-path.ts | `packages/next/src/shared/lib/encode-uri-path.ts` | ソース | URIパスのエンコード処理 |
| next-font-manifest-plugin.ts | `packages/next/src/build/webpack/plugins/next-font-manifest-plugin.ts` | ソース | NextFontManifest型定義 |
| constants.ts | `packages/next/src/shared/lib/constants.ts` | ソース | NEXT_BUILTIN_DOCUMENT定数 |
