# 帳票設計書 16-middleware-react-loadable-manifest.js

## 概要

本ドキュメントは、Next.jsビルドプロセスにおいて生成される `middleware-react-loadable-manifest.js`（ミドルウェア用React Loadableマニフェスト）の設計仕様を定義する。本マニフェストは、エッジランタイム向けにReact Loadable（動的インポート）のチャンク情報をJavaScript形式で提供する。

### 本帳票の処理概要

本マニフェストは、`react-loadable-manifest.json` の内容をエッジランタイムで利用可能なJavaScript変数形式に変換したファイルである。WebpackのReactLoadablePluginにより `react-loadable-manifest.json` と同時に生成される。

**業務上の目的・背景**：Next.jsの `next/dynamic`（React.lazy/React.loadable）による動的インポートでは、サーバーサイドレンダリング時にどのチャンクをプリロードすべきかの情報が必要である。エッジランタイム環境ではJSON形式のマニフェストを直接読み込めないため、`self.__REACT_LOADABLE_MANIFEST` 変数としてJavaScript形式で提供する必要がある。

**帳票の利用シーン**：`next build` コマンド実行時にWebpackコンパイルフェーズで自動生成される。エッジランタイムで実行されるSSRページが、動的インポートされたコンポーネントのチャンクファイルを特定する際に利用される。

**主要な出力内容**：
1. 各動的インポートモジュールのID情報
2. 各動的インポートモジュールに対応するチャンクファイルリスト
3. `self.__REACT_LOADABLE_MANIFEST` 変数としてのマッピング

**帳票の出力タイミング**：Webpackコンパイルフェーズの `PROCESS_ASSETS_STAGE_ADDITIONS` ステージで `ReactLoadablePlugin` により生成される。Webpack設定の `webpack-config.ts` でプラグインが登録される。

**帳票の利用者**：エッジランタイムで実行されるNext.jsのSSRページ。ミドルウェアプラグインを通じてエッジファイルリストに含められる。

## 帳票種別

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

## 利用画面

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

## 出力形式

### 基本仕様

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

### JavaScript形式

```javascript
self.__REACT_LOADABLE_MANIFEST="{\"moduleId\":{\"id\":\"chunkId\",\"files\":[\"static/chunks/dynamic-page.js\"]}}"
```

## 帳票レイアウト

### レイアウト概要

react-loadable-manifest.jsonの内容をJSON文字列化してJavaScript変数に格納する。

```
┌────────────────────────────────────────────────────────────┐
│  self.__REACT_LOADABLE_MANIFEST = JSON.stringify({         │
│    [moduleId: string]: {                                   │
│      id: string | number                                   │
│      files: string[]                                       │
│    }                                                       │
│  })                                                        │
└────────────────────────────────────────────────────────────┘
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | moduleId（キー） | 動的インポートされたモジュールの識別子 | Webpackモジュールグラフ | 文字列 |
| 2 | id | チャンクグループのモジュールID | Webpackチャンクグラフ | `string \| number` |
| 3 | files | モジュールに対応するチャンクファイルリスト | Webpackチャンクグループ | `string[]` |

### 明細部

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

### フッター部

N/A

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| ビルド実行 | Webpackによるビルドが実行されること | Yes |
| runtimeAsset設定 | ReactLoadablePluginのruntimeAssetオプションが指定されていること | Yes |

### ソート順

N/A

### 改ページ条件

N/A

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

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

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| マニフェスト変換 | `self.__REACT_LOADABLE_MANIFEST=${JSON.stringify(JSON.stringify(manifest))}` | N/A | 二重JSON.stringifyでエスケープ |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[Webpackコンパイル] --> B[ReactLoadablePlugin]
    B --> C[動的インポートモジュール収集]
    C --> D[チャンクファイルマッピング構築]
    D --> E{runtimeAsset設定あり?}
    E -->|Yes| F[self.__REACT_LOADABLE_MANIFEST形式で出力]
    E -->|No| G[スキップ]
    F --> H[server/middleware-react-loadable-manifest.js出力]
    H --> I[終了]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| 動的インポートなし | プロジェクトに動的インポートが存在しない場合 | エラーなし（空のマニフェスト） | 対処不要 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | プロジェクト内の動的インポート数に依存 |
| 目標出力時間 | JSON変換のみ（即座） |
| 同時出力数上限 | 1 |

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

チャンクファイルパス情報のみを含み、機密情報は含まれない。

## 備考

- 定数名 `MIDDLEWARE_REACT_LOADABLE_MANIFEST` は `constants.ts` の132-133行目で定義（値: `'middleware-react-loadable-manifest'`）。
- Webpack設定（`webpack-config.ts`）で ReactLoadablePlugin に `runtimeAsset` オプションとして `server/${MIDDLEWARE_REACT_LOADABLE_MANIFEST}.js` が指定される。
- ミドルウェアプラグイン（middleware-plugin.ts 133行目）で、エッジSSRのファイルリストに本マニフェストが含まれる。
- 二重 `JSON.stringify` される理由は、エッジランタイムで `JSON.parse` を1回呼ぶだけでオブジェクトに復元できるようにするため。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | load-components.ts | `packages/next/src/server/load-components.ts` | 38-43行目: `ManifestItem` 型（id, files）と `ReactLoadableManifest` 型定義 |
| 1-2 | constants.ts | `packages/next/src/shared/lib/constants.ts` | 132-133行目: `MIDDLEWARE_REACT_LOADABLE_MANIFEST` 定数 |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | react-loadable-plugin.ts | `packages/next/src/build/webpack/plugins/react-loadable-plugin.ts` | 207-216行目: `runtimeAsset` が設定されている場合に `self.__REACT_LOADABLE_MANIFEST` 形式で出力 |

**主要処理フロー**:
- **207行目**: `if (this.runtimeAsset)` で runtimeAsset 設定チェック
- **210-212行目**: `self.__REACT_LOADABLE_MANIFEST=${JSON.stringify(JSON.stringify(reactLoadableManifest))}` で二重stringify

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | middleware-plugin.ts | `packages/next/src/build/webpack/plugins/middleware-plugin.ts` | 133行目: エッジSSRファイルリストに `server/${MIDDLEWARE_REACT_LOADABLE_MANIFEST}.js` を追加 |
| 3-2 | route-loader.ts | `packages/next/src/client/route-loader.ts` | 18行目: `window.__REACT_LOADABLE_MANIFEST` グローバル変数宣言 |

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

```
next build
    |
    +-- Webpack Compilation
    |       |
    |       +-- ReactLoadablePlugin.apply()
    |               |
    |               +-- buildManifest() [動的インポート情報収集]
    |               +-- compilation.emitAsset(runtimeAsset)
    |                       +-- self.__REACT_LOADABLE_MANIFEST 出力
    |
    +-- MiddlewarePlugin
            +-- getEntryFiles()
                    +-- server/middleware-react-loadable-manifest.js をファイルリストに追加
```

### データフロー図

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

Webpack dynamic imports    ReactLoadablePlugin              .next/server/middleware-react-loadable-manifest.js
  (next/dynamic)       --> (チャンクマッピング構築)      -->
                           JSON.stringify x 2で変換

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

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| react-loadable-plugin.ts | `packages/next/src/build/webpack/plugins/react-loadable-plugin.ts` | ソース | ReactLoadablePlugin。マニフェスト生成 |
| constants.ts | `packages/next/src/shared/lib/constants.ts` | ソース | `MIDDLEWARE_REACT_LOADABLE_MANIFEST` 定数定義 |
| middleware-plugin.ts | `packages/next/src/build/webpack/plugins/middleware-plugin.ts` | ソース | エッジファイルリストへの追加 |
| webpack-config.ts | `packages/next/src/build/webpack-config.ts` | ソース | プラグイン登録・runtimeAssetオプション設定 |
| load-components.ts | `packages/next/src/server/load-components.ts` | ソース | ReactLoadableManifest型定義 |
| route-loader.ts | `packages/next/src/client/route-loader.ts` | ソース | クライアントグローバル変数宣言 |
