# 帳票設計書 15-middleware-build-manifest.js

## 概要

本ドキュメントは、Next.jsビルドプロセスにおいて生成される `middleware-build-manifest.js`（ミドルウェア用ビルドマニフェスト）の設計仕様を定義する。本マニフェストは、エッジランタイム向けにビルドマニフェスト（build-manifest.json）の内容をJavaScript形式で提供し、ミドルウェアやエッジSSRがアセット情報にアクセスできるようにする。

### 本帳票の処理概要

本マニフェストは、Webpackの `BuildManifestPlugin` により生成されるJavaScriptファイルであり、`build-manifest.json` と同等の内容をエッジランタイム（ミドルウェア・エッジSSR）で利用可能な形式に変換して出力する。エッジランタイムはファイルシステムに直接アクセスできないため、JavaScriptのグローバル変数として情報を提供する必要がある。

**業務上の目的・背景**：Next.jsのミドルウェアおよびエッジSSRは、V8 Isolateベースのエッジランタイム環境で実行される。このランタイムにはNode.jsのファイルシステムAPIがないため、JSON形式のマニフェストを直接読み込めない。本マニフェストはビルドマニフェスト情報をJavaScriptの `globalThis.__BUILD_MANIFEST` 変数として提供し、エッジランタイムでのアセット解決を可能にする。

**帳票の利用シーン**：`next build` コマンド実行時に `BuildManifestPlugin` により自動生成される。エッジランタイムで実行されるミドルウェアやエッジSSRページがクライアントアセット（JavaScript/CSSファイル）のリストを参照する際に利用される。Turbopack使用時は `TurbopackManifestLoader` の `writeBuildManifest` メソッドにより生成される。

**主要な出力内容**：
1. ビルドマニフェストの全内容（各ページに対応するJS/CSSファイルリスト）
2. `globalThis.__BUILD_MANIFEST` 変数としてのアセットマッピング

**帳票の出力タイミング**：Webpackコンパイルフェーズの `PROCESS_ASSETS_STAGE_ADDITIONS` ステージで `BuildManifestPlugin` により生成される。

**帳票の利用者**：エッジランタイムで実行されるNext.jsのミドルウェアおよびエッジSSRページ。

## 帳票種別

ビルドマニフェスト（JavaScript形式・エッジランタイム向け）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| N/A | CLIコマンド | `next build` | ビルド実行 |
| N/A | 開発サーバー | `next dev` | 開発サーバー起動 |

## 出力形式

### 基本仕様

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

### JavaScript形式

```javascript
globalThis.__BUILD_MANIFEST = {
  "pages": {
    "/_app": ["static/chunks/main.js"],
    "/": ["static/chunks/pages/index.js"],
    "/about": ["static/chunks/pages/about.js"]
  },
  "devFiles": [],
  "polyfillFiles": [],
  "lowPriorityFiles": [],
  "rootMainFiles": []
};
```

## 帳票レイアウト

### レイアウト概要

JavaScript変数代入文としてビルドマニフェストの全内容を含む。

```
┌──────────────────────────────────────────────┐
│  globalThis.__BUILD_MANIFEST = {             │
│    pages: { [route]: string[] }              │
│    devFiles: string[]                        │
│    polyfillFiles: string[]                   │
│    lowPriorityFiles: string[]                │
│    rootMainFiles: string[]                   │
│  }                                           │
└──────────────────────────────────────────────┘
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | pages | 各ルートのJS/CSSファイルリスト | BuildManifest | `{ [route: string]: string[] }` |
| 2 | devFiles | 開発用ファイルリスト | BuildManifest | `string[]` |
| 3 | polyfillFiles | ポリフィルファイルリスト | BuildManifest | `string[]` |
| 4 | lowPriorityFiles | 低優先度ファイルリスト | BuildManifest | `string[]` |
| 5 | rootMainFiles | ルートメインファイルリスト | BuildManifest | `string[]` |

### 明細部

N/A（build-manifest.jsonと同一構造）

### フッター部

N/A

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| ビルド実行 | Webpackまたは Turbopackによるビルドが実行されること | Yes |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | pagesのキー | アルファベット昇順（ソート済み） |

### 改ページ条件

N/A

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

N/A（Webpackコンパイル結果から生成）

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| マニフェスト変換 | `globalThis.__BUILD_MANIFEST = ${JSON.stringify(assetMap)}` | N/A | JSONをJS変数代入形式に変換 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[Webpackコンパイル] --> B[BuildManifestPlugin]
    B --> C[assetMap構築]
    C --> D[createEdgeRuntimeManifest呼び出し]
    D --> E[globalThis.__BUILD_MANIFEST = JSON形式に変換]
    E --> F[server/middleware-build-manifest.js出力]
    F --> G[終了]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| アセット情報なし | コンパイル結果が空の場合 | エラーなし（空のマニフェスト生成） | 対処不要 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | build-manifest.jsonと同一 |
| 目標出力時間 | JSON.stringify変換のみ（即座） |
| 同時出力数上限 | 1 |

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

ビルドマニフェストのアセットパス情報のみを含み、機密情報は含まれない。エッジランタイム環境での利用を前提とし、`globalThis` 変数として公開される。

## 備考

- `createEdgeRuntimeManifest` 関数は `build-manifest-plugin-utils.ts` で定義され、`globalThis.__BUILD_MANIFEST = ${JSON.stringify(assetMap)}\n` 形式の文字列を返す。
- エッジランタイムでは `self` の代わりに `globalThis` が使用される（ミドルウェアがNode.jsランタイムの場合もあるため）。
- Turbopack使用時は `TurbopackManifestLoader.writeBuildManifest` メソッド（manifest-loader.ts 534-546行目）で同等のファイルが生成される。
- ミドルウェアプラグイン（middleware-plugin.ts 132行目）で、エッジSSRのファイルリストに本マニフェストが含まれる。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | constants.ts | `packages/next/src/shared/lib/constants.ts` | 130行目: `MIDDLEWARE_BUILD_MANIFEST` 定数（値: `'middleware-build-manifest'`） |
| 1-2 | build-manifest-plugin-utils.ts | `packages/next/src/build/webpack/plugins/build-manifest-plugin-utils.ts` | 52-58行目: `createEdgeRuntimeManifest` 関数。`globalThis.__BUILD_MANIFEST` 形式への変換 |

**読解のコツ**: 本マニフェストはbuild-manifest.jsonの内容をJS変数として提供するラッパーである。データ構造自体はBuildManifest型と同一。

#### Step 2: Webpack生成処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | build-manifest-plugin.ts | `packages/next/src/build/webpack/plugins/build-manifest-plugin.ts` | 262-264行目: `compilation.emitAsset` で `server/middleware-build-manifest.js` を出力。`createEdgeRuntimeManifest(assetMap)` を使用 |

**主要処理フロー**:
- **263行目**: `server/${MIDDLEWARE_BUILD_MANIFEST}.js` をアセット名として出力
- **264行目**: `createEdgeRuntimeManifest(assetMap)` で内容生成

#### Step 3: Turbopack生成処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | manifest-loader.ts | `packages/next/src/shared/lib/turbopack/manifest-loader.ts` | 534-546行目: `writeBuildManifest` メソッド。マージされたビルドマニフェストからmiddleware-build-manifest.jsを生成 |

#### Step 4: エッジランタイムでの参照を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | middleware-plugin.ts | `packages/next/src/build/webpack/plugins/middleware-plugin.ts` | 132行目: `getEntryFiles` 関数内でエッジSSRのファイルリストに `server/${MIDDLEWARE_BUILD_MANIFEST}.js` を追加 |

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

```
next build
    |
    +-- [Webpack] BuildManifestPlugin.apply()
    |       |
    |       +-- compilation.hooks.processAssets.tap()
    |               |
    |               +-- assetMap構築
    |               +-- createEdgeRuntimeManifest(assetMap)
    |               +-- compilation.emitAsset('server/middleware-build-manifest.js')
    |
    +-- [Turbopack] TurbopackManifestLoader.writeBuildManifest()
            |
            +-- mergeBuildManifests()
            +-- createEdgeRuntimeManifest(buildManifest)
            +-- writeFileAtomic('server/middleware-build-manifest.js')
```

### データフロー図

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

build-manifest.json    createEdgeRuntimeManifest()        .next/server/middleware-build-manifest.js
  (アセットマップ)  --> (globalThis変数形式に変換)    -->

                       MiddlewarePlugin                   エッジランタイムでの
  manifest.js      --> (ファイルリスト参照)           -->  __BUILD_MANIFEST アクセス
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| build-manifest-plugin.ts | `packages/next/src/build/webpack/plugins/build-manifest-plugin.ts` | ソース | Webpackプラグイン。マニフェスト生成 |
| build-manifest-plugin-utils.ts | `packages/next/src/build/webpack/plugins/build-manifest-plugin-utils.ts` | ソース | `createEdgeRuntimeManifest` 関数定義 |
| constants.ts | `packages/next/src/shared/lib/constants.ts` | ソース | `MIDDLEWARE_BUILD_MANIFEST` 定数定義 |
| manifest-loader.ts | `packages/next/src/shared/lib/turbopack/manifest-loader.ts` | ソース | Turbopack時のマニフェスト生成 |
| middleware-plugin.ts | `packages/next/src/build/webpack/plugins/middleware-plugin.ts` | ソース | エッジランタイムでのファイルリスト参照 |
| index.ts | `packages/next/src/build/index.ts` | ソース | ビルドプロセスのエントリポイント |
