# 機能設計書 21-ランタイムチャンク分離

## 概要

本ドキュメントは、webpackのRuntimeChunkPluginによるランタイムコードの独立チャンク分離機能について記述する。

### 本機能の処理概要

RuntimeChunkPluginは、webpackのランタイムコード（モジュール読み込み・チャンク管理等のブートストラップコード）をエントリポイントのバンドルから分離し、独立したチャンクとして出力する機能を提供する。

**業務上の目的・背景**：webpackランタイムコードはビルドごとに変化しやすく、エントリポイントに含めるとキャッシュ効率が低下する。ランタイムを独立チャンクに分離することで、アプリケーションコードのキャッシュ有効期間を延長し、ユーザーのページ読み込み速度を向上させる。特に複数エントリポイントを持つアプリケーションでは、共通ランタイムの共有によりバンドルサイズも削減される。

**機能の利用シーン**：複数エントリポイントを持つマルチページアプリケーション（MPA）や、長期キャッシュ戦略を採用するSPA/PWAにおいて、`optimization.runtimeChunk` 設定を通じて利用される。`runtimeChunk: 'single'` で全エントリポイントが1つのランタイムチャンクを共有し、`runtimeChunk: true` または `runtimeChunk: 'multiple'` で各エントリポイントごとに独立したランタイムチャンクが生成される。

**主要な処理内容**：
1. コンパイルフック `thisCompilation` を通じてCompilationインスタンスにアクセスする
2. `addEntry` フックでエントリポイント追加時にインターセプトする
3. エントリポイントのruntimeオプションが未設定かつdependOnが未設定の場合、ランタイムチャンク名を決定する
4. エントリデータの `options.runtime` にランタイムチャンク名を設定する

**関連システム・外部連携**：webpack設定の `optimization.runtimeChunk` オプションと連携する。`runtimeChunk: 'single'` の場合は全エントリポイントに同一のランタイム名 `"runtime"` を設定し、`runtimeChunk: true` の場合はデフォルトの命名規則 `runtime~{entryName}` を使用する。

**権限による制御**：本機能に権限による制御はない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 17 | App (code-splitting-depend-on-advanced) | 補助機能 | runtimeChunk:'single'設定によるランタイムコードの独立チャンク化 |
| 18 | Page 1 (code-splitting-depend-on-advanced) | 補助機能 | 共有ランタイムチャンクの利用 |

## 機能種別

データ変換処理（エントリポイントメタデータへのランタイムチャンク名注入）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| options.name | string \| function | No | ランタイムチャンク名またはチャンク名生成関数 | デフォルトは `(entrypoint) => \`runtime~${entrypoint.name}\`` |

### 入力データソース

webpack設定の `optimization.runtimeChunk` オプション。WebpackOptionsApplyにおいて `RuntimeChunkPlugin` のコンストラクタに渡される。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| data.options.runtime | string | エントリデータに設定されるランタイムチャンク名 |

### 出力先

Compilationオブジェクトのエントリデータ（`compilation.entries`）のruntimeプロパティ。

## 処理フロー

### 処理シーケンス

```
1. プラグイン適用（apply）
   └─ compiler.hooks.thisCompilation にタップ
2. コンパイル開始時（thisCompilationフック発火）
   └─ compilation.hooks.addEntry にタップ
3. エントリポイント追加時（addEntryフック発火）
   ├─ entryNameがundefinedの場合 → 何もしない（return）
   ├─ compilation.entries から entryName に対応するEntryDataを取得
   ├─ data.options.runtime が既に設定済み → 何もしない
   ├─ data.options.dependOn が設定済み → 何もしない
   └─ ランタイムチャンク名を決定し data.options.runtime に設定
       ├─ this.options.name が関数の場合 → 関数を呼び出して名前を取得
       └─ this.options.name が文字列の場合 → そのまま使用
```

### フローチャート

```mermaid
flowchart TD
    A[addEntryフック発火] --> B{entryNameが定義済み?}
    B -->|No| Z[何もしない]
    B -->|Yes| C[EntryDataを取得]
    C --> D{runtime未設定 AND dependOn未設定?}
    D -->|No| Z
    D -->|Yes| E{nameが関数?}
    E -->|Yes| F[関数を呼び出してランタイム名を取得]
    E -->|No| G[文字列をそのまま使用]
    F --> H[data.options.runtime に設定]
    G --> H
    H --> Z
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | ランタイム名未設定条件 | runtime が既に設定されている場合はスキップ | 常時 |
| BR-02 | dependOn排他条件 | dependOnが設定されている場合はランタイム分離しない | エントリにdependOnが指定されている場合 |
| BR-03 | デフォルト命名規則 | デフォルトは `runtime~{エントリポイント名}` | nameオプション未指定時 |

### 計算ロジック

ランタイムチャンク名の決定ロジック：
- `options.name` が関数の場合: `name({ name: entryName })` を呼び出し
- `options.name` が文字列の場合: そのまま使用
- デフォルト: `` `runtime~${entrypoint.name}` ``

## データベース操作仕様

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

本機能にデータベース操作はない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | - | 本機能固有のエラー処理はない | - |

### リトライ仕様

リトライ処理はない。

## トランザクション仕様

トランザクション管理はない。

## パフォーマンス要件

本プラグインの処理はエントリポイント追加時の同期的なメタデータ設定のみであり、パフォーマンスへの影響は無視できる程度である。

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

本機能にセキュリティ上の考慮事項はない。

## 備考

- `optimization.runtimeChunk: 'single'` を指定すると、内部的に `name: () => "runtime"` が設定される
- `optimization.runtimeChunk: true` または `'multiple'` を指定すると、デフォルト命名規則が使用される
- `dependOn` オプションとの併用時は、dependOn側で指定されたエントリのランタイムが使用されるため、本プラグインの処理はスキップされる

---

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

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

### 推奨読解順序

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

エントリポイントに関わるデータ構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Compilation.js | `lib/Compilation.js` | `EntryData` 型定義（`options.runtime` プロパティ） |

**読解のコツ**: `EntryData` は `{ dependencies, includeDependencies, options }` の構造を持ち、`options.runtime` がランタイムチャンク名を保持する。`options.dependOn` との排他関係を理解することが重要。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | RuntimeChunkPlugin.js | `lib/optimize/RuntimeChunkPlugin.js` | プラグイン全体（52行のコンパクトなファイル） |

**主要処理フロー**:
1. **11行目**: プラグイン名定数の定義 `"RuntimeChunkPlugin"`
2. **19-25行目**: コンストラクタ。デフォルトのname関数を定義（`` `runtime~${entrypoint.name}` ``）
3. **32-48行目**: `apply` メソッド。`thisCompilation` -> `addEntry` のフックチェーンで処理を登録
4. **34行目**: `addEntry` フックのコールバック。entryNameとEntryDataを受け取る
5. **35行目**: entryNameがundefinedの場合は早期リターン
6. **36-38行目**: compilation.entriesからEntryDataを取得
7. **39行目**: runtimeが未設定かつdependOnが未設定の場合のみ処理を継続
8. **41-44行目**: name関数または文字列からランタイムチャンク名を決定
9. **45行目**: `data.options.runtime` にランタイムチャンク名を設定

#### Step 3: 設定からの呼び出しを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | WebpackOptionsApply.js | `lib/config/WebpackOptionsApply.js` | `optimization.runtimeChunk` 設定に基づくプラグイン適用処理 |

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

```
webpack設定 (optimization.runtimeChunk)
    │
    ├─ WebpackOptionsApply
    │      └─ new RuntimeChunkPlugin(options).apply(compiler)
    │
    └─ RuntimeChunkPlugin.apply(compiler)
           └─ compiler.hooks.thisCompilation.tap()
                  └─ compilation.hooks.addEntry.tap()
                         └─ data.options.runtime = name
```

### データフロー図

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

optimization.runtimeChunk ──▶ WebpackOptionsApply ──▶ RuntimeChunkPlugin
    (true/single/object)          (設定解釈)              (プラグイン適用)

entryName ──────────────────▶ addEntryフック ────────▶ data.options.runtime
    (エントリポイント名)          (ランタイム名決定)        (ランタイムチャンク名)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| RuntimeChunkPlugin.js | `lib/optimize/RuntimeChunkPlugin.js` | ソース | 本機能のメインプラグイン |
| Compilation.js | `lib/Compilation.js` | ソース | EntryData型定義、addEntryフック提供 |
| WebpackOptionsApply.js | `lib/config/WebpackOptionsApply.js` | ソース | 設定からプラグインの適用 |
| Compiler.js | `lib/Compiler.js` | ソース | thisCompilationフック提供 |
