# 機能設計書 4-エントリポイント管理

## 概要

本ドキュメントは、webpack設定のentryオプションに基づきエントリポイントを登録・処理する機能の設計を記述する。EntryPlugin / DynamicEntryPluginを中心とした実装である。

### 本機能の処理概要

エントリポイント管理は、webpackビルドの起点となるモジュールを登録し、そこからモジュールグラフの構築を開始する機能である。静的エントリ（EntryPlugin）と動的エントリ（DynamicEntryPlugin）の両方をサポートし、dependOn設定によるエントリ間の依存関係も管理する。

**業務上の目的・背景**：マルチページアプリケーションやコード分割を実現するためには、複数のエントリポイントを柔軟に定義する必要がある。エントリポイント管理機能は、webpack設定のentry定義を解析し、ビルドプロセスに組み込む。

**機能の利用シーン**：webpack.config.jsのentryフィールドで指定されたモジュールが、この機能を通じてCompilationに登録される。多くの画面で「エントリポイントとして登録され...」として参照されている。

**主要な処理内容**：
1. EntryPlugin.apply()でCompilerのcompilationフックにEntryDependencyファクトリを登録
2. makeフックでCompilation.addEntry()を呼び出しエントリポイントを追加
3. EntryDependencyの生成とコンテキスト情報の設定
4. DynamicEntryPluginによる関数ベースの動的エントリ解決
5. EntryOptionPluginによるエントリ設定の解析とプラグイン適用

**関連システム・外部連携**：EntryDependency（エントリ依存関係クラス）、EntryOptionPlugin（エントリ設定解析プラグイン）、Compilation.addEntry()（エントリ追加API）と連携する。

**権限による制御**：特になし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | Page A (many-pages) | 主機能 | エントリポイントとして登録、モジュールm1,m2,m3等を読み込み |
| 2 | Page B (many-pages) | 主機能 | エントリポイントとして登録、モジュールm1,m2,m4等を読み込み |
| 3 | Page C (many-pages) | 主機能 | エントリポイントとして登録、モジュールm1,m2,m5等を読み込み |
| 4 | Page D (many-pages) | 主機能 | エントリポイントとして登録、モジュールm6,m7,m8等を読み込み |
| 5 | Page E (many-pages) | 主機能 | エントリポイントとして登録、モジュールm6,m7,m8等を読み込み |
| 6 | Page F (many-pages) | 主機能 | エントリポイントとして登録 |
| 7 | Page G (many-pages) | 主機能 | エントリポイントとして登録 |
| 8 | Page A (hybrid-routing) | 主機能 | aEntryおよびrouterと共にエントリポイントとして登録 |
| 9 | Page B (hybrid-routing) | 主機能 | bEntryおよびrouterと共にエントリポイントとして登録 |
| 12 | Page A (multiple-entry-points) | 主機能 | 複数エントリポイントの一つとして登録 |
| 13 | Page B (multiple-entry-points) | 主機能 | 複数エントリポイントの一つとして登録 |
| 14 | Page A (two-explicit-vendor-chunks) | 主機能 | vendor1,vendor2と共にエントリポイントとして登録 |
| 17 | App (code-splitting-depend-on-advanced) | 主機能 | dependOn設定によりother-vendorsに依存 |
| 18 | Page 1 (code-splitting-depend-on-advanced) | 主機能 | dependOn設定によりappおよびreact-vendorsに依存 |

## 機能種別

設定解析 / モジュール登録 / オーケストレーション

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| context | string | Yes | エントリの基準ディレクトリパス | 絶対パスであること |
| entry | string | Yes | エントリモジュールのパス | 解決可能なモジュールパス |
| options | EntryOptions \| string | No | エントリオプション（名前、dependOn等） | - |

### 入力データソース

- webpack.config.jsのentryフィールド（文字列、配列、オブジェクト、関数形式）
- EntryOptionPluginによる正規化済み設定

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| EntryDependency | EntryDependency | 生成されたエントリ依存関係オブジェクト |
| Entrypoint | Entrypoint | Compilationに登録されたエントリポイント |

### 出力先

- CompilationのaddEntry()を通じてモジュールグラフに登録される
- Compilation.entrypointsマップに格納される

## 処理フロー

### 処理シーケンス

```
1. EntryPlugin.apply(compiler) 呼び出し
   ├─ compilationフック: EntryDependencyファクトリを登録
   └─ makeフック: compilation.addEntry()を呼び出し
2. EntryPlugin.createDependency(entry, options)
   └─ EntryDependencyインスタンス生成、locにname設定
3. compilation.addEntry(context, dep, options, callback)
   └─ モジュールグラフ構築の起点となる
4. [DynamicEntryPluginの場合]
   ├─ entry関数を呼び出してエントリ設定を取得
   ├─ 各エントリについてEntryOptionPlugin.entryDescriptionToOptions()でオプション変換
   └─ 各importパスについてcompilation.addEntry()を呼び出し
```

### フローチャート

```mermaid
flowchart TD
    A[webpack設定のentry] --> B{関数型?}
    B -->|Yes| C[DynamicEntryPlugin]
    B -->|No| D[EntryOptionPlugin解析]
    C --> E[entry関数呼び出し]
    E --> F[EntryPlugin.createDependency]
    D --> G[エントリごとにEntryPlugin生成]
    G --> F
    F --> H[compilation.addEntry]
    H --> I[モジュールグラフ構築開始]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 静的エントリ | 文字列・配列・オブジェクト形式のエントリは静的に解決 | entry設定が関数でない場合 |
| BR-02 | 動的エントリ | 関数形式のエントリは毎コンパイル時に動的に解決 | entry設定が関数の場合 |
| BR-03 | dependOn | エントリ間の依存関係を設定し、共有ランタイムを制御 | dependOnオプション指定時 |
| BR-04 | エントリ名設定 | EntryDependency.locにエントリ名を設定（デバッグ・統計用） | 常時 |

### 計算ロジック

特になし。

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

該当なし。

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

該当なし。

### テーブル別操作詳細

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ModuleNotFoundError | 解決エラー | エントリモジュールのパスが解決できない | パスを確認 |
| Promise rejection | 動的エントリエラー | entry関数がPromise.rejectを返した | entry関数を修正 |

### リトライ仕様

リトライ機構はない。動的エントリの場合はコンパイルごとに再実行される。

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

該当なし。

## パフォーマンス要件

- 静的エントリはプラグイン適用時に一度だけ解決される
- 動的エントリはコンパイルごとに解決されるため、entry関数の実行時間がビルド時間に影響する

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

- 動的エントリの関数はビルド環境で実行されるため、信頼されたコードであること

## 備考

- EntryPluginはwebpackの最も基本的なプラグインの一つ
- makeフックはAsyncParallelHookであるため、複数のEntryPluginが並列にエントリを追加できる

---

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

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

### 推奨読解順序

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

EntryDependencyとEntryOptionsの構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | EntryDependency.js | `lib/dependencies/EntryDependency.js` | EntryDependencyクラスの構造を理解する |
| 1-2 | Entrypoint.js | `lib/Entrypoint.js` | EntryOptionsの型定義を理解する |

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

EntryPlugin.apply()がCompilerに登録される流れを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | EntryPlugin.js | `lib/EntryPlugin.js` | apply()メソッド（33-51行目）でcompilationフックとmakeフックの登録を理解する |
| 2-2 | EntryPlugin.js | `lib/EntryPlugin.js` | createDependency()（59-69行目）でEntryDependency生成を理解する |

**主要処理フロー**:
1. **34-42行目**: compilationフックでEntryDependencyファクトリをNormalModuleFactoryに設定
2. **47-51行目**: makeフックでcompilation.addEntry()を呼び出し

#### Step 3: 動的エントリを理解する

DynamicEntryPluginの動作を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | DynamicEntryPlugin.js | `lib/DynamicEntryPlugin.js` | apply()メソッド（39-90行目）で動的エントリ解決の流れを理解する |

**主要処理フロー**:
- **50-89行目**: makeフックでentry関数を呼び出し、Promise解決後に各エントリをaddEntry

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

```
EntryOptionPlugin.apply(compiler)
    │
    ├─ compiler.hooks.entryOption.tap()
    │      └─ 各エントリについてEntryPlugin / DynamicEntryPluginを適用
    │
    └─ EntryPlugin.apply(compiler) / DynamicEntryPlugin.apply(compiler)
           │
           ├─ compiler.hooks.compilation.tap()
           │      └─ compilation.dependencyFactories.set(EntryDependency, normalModuleFactory)
           │
           └─ compiler.hooks.make.tapAsync() / tapPromise()
                  └─ compilation.addEntry(context, dep, options, callback)
                         └─ モジュールグラフ構築開始
```

### データフロー図

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

webpack.config.entry ──▶ EntryOptionPlugin ──────▶ EntryPlugin群
                                │
                         EntryPlugin.apply()
                                │
                         createDependency() ─────▶ EntryDependency
                                │
                         compilation.addEntry() ──▶ Entrypoint
                                                     モジュールグラフ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| EntryPlugin.js | `lib/EntryPlugin.js` | ソース | 静的エントリポイントの登録 |
| DynamicEntryPlugin.js | `lib/DynamicEntryPlugin.js` | ソース | 動的エントリポイントの登録 |
| EntryOptionPlugin.js | `lib/EntryOptionPlugin.js` | ソース | エントリ設定の解析とプラグイン適用 |
| EntryDependency.js | `lib/dependencies/EntryDependency.js` | ソース | エントリ依存関係クラス |
| Entrypoint.js | `lib/Entrypoint.js` | ソース | エントリポイントクラス（ChunkGroupの派生） |
