# 帳票設計書 1-build-manifest.json

## 概要

本ドキュメントは、Next.jsビルドプロセスにおいて生成される `build-manifest.json` の設計を記述する。このマニフェストは、ビルド時に各ページに必要なJavaScript/CSSファイルのマッピング情報を提供し、クライアント・サーバー間で共有されるアセット情報の中核を担う。

### 本帳票の処理概要

build-manifest.json は、Next.jsのWebpackビルドにおいて `BuildManifestPlugin` によって生成されるJSONファイルである。各ページエントリポイントから実際のアセットファイル名へのマッピングを保持し、サーバーサイドレンダリング時に正しいJavaScript/CSSファイルをHTMLに挿入するために使用される。

**業務上の目的・背景**：Next.jsはビルド時にコード分割を行い、各ページに必要なチャンクファイルを自動的に決定する。本番ビルドではファイル名にハッシュが付与されるため、エントリ名と実際のファイル名の対応関係を管理するマニフェストが不可欠である。build-manifest.jsonはこの対応関係を一元管理し、サーバーがHTMLレスポンスを構築する際に正確なスクリプトタグを生成できるようにする。

**帳票の利用シーン**：サーバーサイドレンダリング（SSR）時にHTMLレスポンスにスクリプトタグを挿入する際、クライアントサイドのページ遷移時に必要なJSチャンクを事前にフェッチする際、開発サーバーでのHMR（Hot Module Replacement）時のアセット解決に使用される。

**主要な出力内容**：
1. `polyfillFiles` - ポリフィルJSファイルのリスト
2. `devFiles` - 開発用ファイル（React Refresh等）のリスト
3. `lowPriorityFiles` - 低優先度ファイル（_buildManifest.js, _ssgManifest.js）のリスト
4. `rootMainFiles` - App Router用のメインJSファイルリスト
5. `rootMainFilesTree` - エントリごとのメインファイルツリー
6. `pages` - ページパスとそのページに必要なJSファイルのマッピング

**帳票の出力タイミング**：`next build` コマンド実行時のWebpackコンパイルプロセス中、`PROCESS_ASSETS_STAGE_ADDITIONS` ステージでBuildManifestPluginが実行された際に出力される。開発モードではWebpackの再コンパイル時に毎回更新される。

**帳票の利用者**：Next.jsサーバーランタイム（SSR処理）、クライアントサイドランタイム（ページ遷移時のアセットロード）、Next.jsデプロイツール、CDNキャッシュ設定担当者。

## 帳票種別

ビルドマニフェスト（JSON形式のアセットマッピングファイル）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| N/A | CLIコマンド | `next build` | ビルドコマンド実行 |
| N/A | 開発サーバー | `next dev` | 開発サーバー起動・ファイル変更時自動生成 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | JSON |
| 用紙サイズ | N/A（データファイル） |
| 向き | N/A |
| ファイル名 | `build-manifest.json` |
| 出力方法 | ファイルシステムへの書き出し（`.next/build-manifest.json`） |
| 文字コード | UTF-8 |

### PDF固有設定

N/A（JSON形式のため該当なし）

### Excel固有設定

N/A（JSON形式のため該当なし）

## 帳票レイアウト

### レイアウト概要

build-manifest.json はJSONオブジェクトとして構成され、トップレベルに6つの主要フィールドを持つ。

```
{
  "polyfillFiles": [...],        // ポリフィルファイル群
  "devFiles": [...],             // 開発用ファイル群
  "lowPriorityFiles": [...],     // 低優先度ファイル群
  "rootMainFiles": [...],        // App Router用メインファイル群
  "rootMainFilesTree": {...},    // エントリごとのメインファイルツリー
  "pages": {                     // ページ別アセットマッピング
    "/_app": [...],
    "/": [...],
    "/about": [...]
  }
}
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | polyfillFiles | ポリフィルとして必要なJSファイルのパス一覧 | Webpackコンパイル結果のアセット情報（`CLIENT_STATIC_FILES_RUNTIME_POLYFILLS_SYMBOL`を持つアセット） | 文字列配列 |
| 2 | devFiles | 開発モードで必要なファイル（React Refresh等） | `CLIENT_STATIC_FILES_RUNTIME_REACT_REFRESH`エントリポイントのファイル | 文字列配列 |
| 3 | lowPriorityFiles | 低優先度でロードされるファイル | `_buildManifest.js`と`_ssgManifest.js`のパス | 文字列配列 |
| 4 | rootMainFiles | App Router用メインエントリファイル | `CLIENT_STATIC_FILES_RUNTIME_MAIN_APP`エントリポイントのファイル | 文字列配列 |
| 5 | rootMainFilesTree | エントリ別メインファイルツリー | ビルドコンテキスト | オブジェクト |

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | pages[ページパス] | 各ページに必要なJS/CSSファイルのリスト | 各エントリポイントの`getFiles()`結果とmainFilesの統合 | 文字列配列 | N/A |

### フッター部

N/A（JSONファイルのため該当なし）

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| エントリポイントフィルタ | `SYSTEM_ENTRYPOINTS`に含まれるエントリは除外 | Yes |
| ファイル形式フィルタ | `.hot-update.js`ファイルは除外、`.js`と`.css`のみ含む | Yes |
| ルート変換 | エントリポイント名から`getRouteFromEntrypoint`でページパスに変換 | Yes |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | ページパス（pages内のキー） | 昇順（アルファベット順） |

### 改ページ条件

N/A（JSONファイルのため該当なし）

## データベース参照仕様

### 参照テーブル一覧

N/A（データベースではなくWebpackコンパイル結果から取得）

### テーブル別参照項目詳細

N/A

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| lowPriorityFilesパス | `static/{buildId}/_buildManifest.js` または `static/_buildManifest.js`（skew protection有効時） | N/A | deploymentIdが設定されている場合はbuildIdを省略 |
| ページ別ファイルリスト | `Set(mainFiles) ∪ Set(entrypointFiles)` | N/A | mainFilesは`CLIENT_STATIC_FILES_RUNTIME_MAIN`のファイル群 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[next build / next dev 実行] --> B[Webpackコンパイル開始]
    B --> C[BuildManifestPlugin.apply - make hookに登録]
    C --> D[processAssets hook発火]
    D --> E[createAssets実行]
    E --> F[エントリポイント一覧取得]
    F --> G[各エントリポイントからファイル一覧抽出]
    G --> H[polyfillFiles/devFiles/lowPriorityFiles構築]
    H --> I[pages マッピング構築]
    I --> J[pagesをキーでソート]
    J --> K[build-manifest.json として出力]
    K --> L[_buildManifest.js クライアント用マニフェスト出力]
    L --> M[middleware-build-manifest.js エッジ用マニフェスト出力]
    M --> N[_ssgManifest.js 出力]
    N --> O[終了]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| コンパイルスパン不在 | compilation spanが取得できない場合 | `No span found for compilation` | Webpackコンパイル設定の確認 |
| ページファイル未検出 | build-manifest内にページが見つからない場合 | `Could not find files for {page} in .next/build-manifest.json` | ビルド設定・ページ構成の確認 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | ページ数に依存（数十〜数千ページ） |
| 目標出力時間 | Webpackコンパイル時間内（個別の計測対象外） |
| 同時出力数上限 | 1（ビルドプロセスにつき1ファイル） |

## セキュリティ考慮事項

build-manifest.jsonにはアプリケーションのルート構造やファイルパスが含まれるため、本番環境では `.next` ディレクトリが直接公開されないように注意が必要。クライアント向けの `_buildManifest.js` は `generateClientManifest` 関数で生成され、`_app` のアセットを除外した軽量版が提供される。deploymentId使用時はskew protectionによりビルドIDの露出が抑制される。

## 備考

- `isDevFallback` が true の場合、ファイル名は `fallback-build-manifest.json` となる
- クライアント向けマニフェスト `_buildManifest.js` は `self.__BUILD_MANIFEST` グローバル変数にセットされる
- エッジランタイム向けには `middleware-build-manifest.js` が `globalThis.__BUILD_MANIFEST` にセットされる
- `clientRouterFilters` が設定されている場合、クライアントマニフェストにBloomFilter情報が含まれる

---

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

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

### 推奨読解順序

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

まず、build-manifest.jsonの型定義とクライアント向けマニフェストの型を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | get-page-files.ts | `packages/next/src/server/get-page-files.ts` | `BuildManifest`型の定義（4〜17行目）。polyfillFiles, devFiles, lowPriorityFiles, rootMainFiles, rootMainFilesTree, pagesの各フィールドの型を確認 |
| 1-2 | build-manifest-plugin-utils.ts | `packages/next/src/build/webpack/plugins/build-manifest-plugin-utils.ts` | `ClientBuildManifest`型（4〜6行目）。クライアント向けマニフェストの簡素化されたキー・値構造を確認 |
| 1-3 | constants.ts | `packages/next/src/shared/lib/constants.ts` | `BUILD_MANIFEST`定数（91行目）、関連する定数群（`CLIENT_STATIC_FILES_RUNTIME_MAIN`等、141〜153行目） |

**読解のコツ**: BuildManifest型は`readonly`修飾子が付いているが、プラグイン内では`DeepMutable<T>`で可変にして操作している。

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

BuildManifestPluginのWebpackプラグインとしてのライフサイクルを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | build-manifest-plugin.ts | `packages/next/src/build/webpack/plugins/build-manifest-plugin.ts` | プラグインクラス定義（114〜304行目）。`apply`メソッド（290〜303行目）でWebpack hookへの登録を確認 |

**主要処理フロー**:
1. **290行目**: `apply` メソッドで `compiler.hooks.make.tap` によりコンパイル開始時にフック登録
2. **292行目**: `compilation.hooks.processAssets.tap` で `PROCESS_ASSETS_STAGE_ADDITIONS` ステージにアセット生成処理を登録
3. **298行目**: `createAssets` メソッドが呼び出される

#### Step 3: アセット生成ロジックを理解する

`createAssets` メソッドの内部処理を詳細に追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | build-manifest-plugin.ts | `packages/next/src/build/webpack/plugins/build-manifest-plugin.ts` | `createAssets`メソッド（148〜288行目）。assetMap構築、ファイル分類、ソート、出力の流れ |

**主要処理フロー**:
- **160〜168行目**: assetMapの初期化。polyfillFiles, devFiles等の空配列とpages初期値を設定
- **170〜172行目**: mainFilesの取得（`CLIENT_STATIC_FILES_RUNTIME_MAIN`エントリから）
- **174〜182行目**: App Router有効時のrootMainFiles設定
- **190〜201行目**: ポリフィルファイルの抽出（`CLIENT_STATIC_FILES_RUNTIME_POLYFILLS_SYMBOL`判定）
- **207〜218行目**: 各エントリポイントをループし、ページパスごとにファイルリストを構築
- **243〜249行目**: pagesキーのソート
- **257〜260行目**: build-manifest.jsonの出力
- **262〜265行目**: middleware-build-manifest.jsの出力
- **267〜286行目**: _buildManifest.js（クライアント向け）の出力

#### Step 4: クライアントマニフェスト生成を理解する

`generateClientManifest` 関数の処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | build-manifest-plugin.ts | `packages/next/src/build/webpack/plugins/build-manifest-plugin.ts` | `generateClientManifest`関数（48〜98行目）。_appのアセットを除外したクライアント向け軽量マニフェスト生成 |

**主要処理フロー**:
- **69〜73行目**: clientManifestにリライト情報とルーターフィルタ情報を設定
- **74行目**: `_app`の依存ファイルセットを構築
- **77〜91行目**: 各ページから`_app`の依存を除外してクライアントマニフェストに追加
- **94行目**: ソート済みページリストを追加
- **96行目**: `devalue`でシリアライズして返却

#### Step 5: ユーティリティ関数を理解する

エッジランタイムマニフェストやリライト正規化の処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | build-manifest-plugin-utils.ts | `packages/next/src/build/webpack/plugins/build-manifest-plugin-utils.ts` | `createEdgeRuntimeManifest`関数（52〜58行目）、`normalizeRewritesForBuildManifest`関数（36〜50行目） |

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

```
next build (packages/next/src/cli/next-build.ts)
    |
    +-- Webpack compilation (packages/next/src/build/webpack-config.ts)
            |
            +-- BuildManifestPlugin.apply() [290行目]
                    |
                    +-- compiler.hooks.make.tap
                            |
                            +-- compilation.hooks.processAssets.tap
                                    |
                                    +-- createAssets() [148行目]
                                            |
                                            +-- getEntrypointFiles() [100行目]
                                            |
                                            +-- getRouteFromEntrypoint()
                                            |       (packages/next/src/server/get-route-from-entrypoint.ts)
                                            |
                                            +-- getSortedRoutes()
                                            |       (packages/next/src/shared/lib/router/utils/index.ts)
                                            |
                                            +-- compilation.emitAsset() [build-manifest.json]
                                            |
                                            +-- createEdgeRuntimeManifest() [build-manifest-plugin-utils.ts:52]
                                            |
                                            +-- generateClientManifest() [48行目]
                                                    |
                                                    +-- normalizeRewritesForBuildManifest()
                                                    |       [build-manifest-plugin-utils.ts:36]
                                                    |
                                                    +-- devalue() シリアライズ
```

### データフロー図

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

Webpack entrypoints ---------> BuildManifestPlugin.createAssets --> .next/build-manifest.json
                                    |
                                    +-> generateClientManifest ----> .next/static/{buildId}/_buildManifest.js
                                    |
                                    +-> createEdgeRuntimeManifest -> .next/server/middleware-build-manifest.js
                                    |
                                    +-> srcEmptySsgManifest -------> .next/static/{buildId}/_ssgManifest.js
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| build-manifest-plugin.ts | `packages/next/src/build/webpack/plugins/build-manifest-plugin.ts` | ソース | メインのプラグイン実装（BuildManifestPlugin, generateClientManifest） |
| build-manifest-plugin-utils.ts | `packages/next/src/build/webpack/plugins/build-manifest-plugin-utils.ts` | ソース | ユーティリティ関数（createEdgeRuntimeManifest, normalizeRewritesForBuildManifest等） |
| get-page-files.ts | `packages/next/src/server/get-page-files.ts` | ソース | BuildManifest型定義、getPageFiles関数 |
| constants.ts | `packages/next/src/shared/lib/constants.ts` | ソース | BUILD_MANIFEST定数、CLIENT_STATIC_FILES_RUNTIME_*定数群 |
| get-route-from-entrypoint.ts | `packages/next/src/server/get-route-from-entrypoint.ts` | ソース | エントリポイント名からルートパスへの変換 |
| webpack-config.ts | `packages/next/src/build/webpack-config.ts` | ソース | BuildManifestPluginのWebpack設定への組み込み |
| index.ts | `packages/next/src/build/index.ts` | ソース | ビルドプロセス全体の制御、マニフェスト読み込み |
| render.tsx | `packages/next/src/server/render.tsx` | ソース | SSR時のbuild-manifest利用 |
| app-render.tsx | `packages/next/src/server/app-render/app-render.tsx` | ソース | App Router SSR時のbuild-manifest利用 |
| manifest-loader.ts | `packages/next/src/shared/lib/turbopack/manifest-loader.ts` | ソース | Turbopack用のマニフェストローダー |
