# 機能設計書 38-コンテナ管理

## 概要

本ドキュメントは、webpackのModule FederationにおけるContainerPlugin / ContainerReferencePluginによるFederationコンテナの作成・参照管理機能について記述する。

### 本機能の処理概要

コンテナ管理機能は、Module Federationにおいて「コンテナ」と呼ばれるモジュール公開・消費の単位を管理する。ContainerPluginがモジュールを外部に公開するコンテナを作成し、ContainerReferencePluginがリモートコンテナからモジュールを取得する仕組みを提供する。

**業務上の目的・背景**：マイクロフロントエンドにおいて、各アプリケーションは「コンテナ」として独立に構成される。コンテナは自身のモジュールの一部を外部に公開（expose）し、他のコンテナのモジュールを消費（consume）できる。この双方向のモジュール共有を安全かつ効率的に管理する必要がある。

**機能の利用シーン**：
- ContainerPlugin: リモートアプリケーション側でコンポーネントやサービスを外部公開する場合
- ContainerReferencePlugin: ホストアプリケーション側でリモートアプリのモジュールを参照する場合

**主要な処理内容**：
1. ContainerPlugin: コンテナエントリモジュールの生成・exposeモジュールの登録
2. ContainerPlugin: リモートエントリファイル（remoteEntry.js）の出力
3. ContainerReferencePlugin: リモートコンテナのExternals登録
4. ContainerReferencePlugin: RemoteModuleの生成・フォールバック処理
5. ContainerReferencePlugin: RemoteRuntimeModuleによるランタイムコード生成

**関連システム・外部連携**：ExternalsPluginと連携してリモートコンテナを外部依存として登録する。リモートエントリファイルはHTTP経由で読み込まれる。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 19 | App (Host) (module-federation) | 参照側 | ContainerReferencePluginによるリモートコンテナの参照・接続 |
| 20 | MFE-B (Remote) (module-federation) | 公開側 | ContainerPluginによるFederationコンテナの作成・モジュール公開 |
| 21 | MFE-C (Remote) (module-federation) | 公開側 | ContainerPluginによるFederationコンテナの作成・モジュール公開 |

## 機能種別

プラグイン / モジュールファクトリ / ランタイムコード生成

## 入力仕様

### 入力パラメータ

#### ContainerPlugin

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| name | string | Yes | コンテナ名 | スキーマバリデーション |
| exposes | object/array | Yes | 公開モジュールの定義 | parseOptions処理 |
| shareScope | string | No | 共有スコープ名（デフォルト: "default"） | スキーマバリデーション |
| library | LibraryOptions | No | ライブラリ出力設定 | スキーマバリデーション |
| filename | string | No | リモートエントリファイル名 | スキーマバリデーション |
| runtime | string | No | ランタイム名 | スキーマバリデーション |

#### ContainerReferencePlugin

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| remoteType | ExternalsType | Yes | リモートの外部タイプ | スキーマバリデーション |
| remotes | object/array | Yes | リモートコンテナの定義 | parseOptions処理 |
| shareScope | string | No | 共有スコープ名（デフォルト: "default"） | スキーマバリデーション |

### 入力データソース

- ModuleFederationPluginから渡される設定オプション
- webpack設定オブジェクト

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ContainerEntryModule | Module | コンテナのエントリモジュール（getメソッドとinitメソッドを公開） |
| RemoteModule | Module | リモートモジュールの参照 |
| RemoteRuntimeModule | RuntimeModule | リモート読み込みのランタイムコード |
| FallbackModule | Module | リモートフォールバック用モジュール |
| リモートエントリファイル | JavaScript | remoteEntry.jsなどの出力ファイル |

### 出力先

output.pathにリモートエントリファイルが出力される。RemoteRuntimeModuleのランタイムコードはバンドル内に含まれる。

## 処理フロー

### 処理シーケンス

```
ContainerPlugin:
1. オプション解析
   └─ parseOptionsでexposeを[key, {import, name}]配列に変換
2. ライブラリタイプ有効化
   └─ enabledLibraryTypesに追加
3. コンテナエントリ登録
   └─ compilation.addEntryでContainerEntryDependencyを追加
4. ContainerEntryModule生成
   └─ get(module, getScope)とinit(shareScope)メソッドを公開

ContainerReferencePlugin:
1. リモート外部参照登録
   └─ ExternalsPluginで"webpack/container/reference/..."キーの外部モジュール登録
2. 依存ファクトリ登録
   └─ RemoteToExternalDependency, FallbackItemDependency, FallbackDependencyを登録
3. モジュールファクトリ
   └─ normalModuleFactory.hooks.factorizeで"container-name/"プレフィックスのリクエストをRemoteModuleに解決
4. RemoteRuntimeModule追加
   └─ チャンク内にリモートモジュールがある場合にランタイムコードを追加
```

### フローチャート

```mermaid
flowchart TD
    A[ContainerPlugin.apply] --> B[parseOptions: exposes解析]
    B --> C[enabledLibraryTypes追加]
    C --> D[compilation.addEntry]
    D --> E[ContainerEntryModule生成]
    E --> F[get/initメソッド公開]

    G[ContainerReferencePlugin.apply] --> H[ExternalsPlugin適用]
    H --> I[依存ファクトリ登録]
    I --> J[factorizeフック: リモートリクエスト検出]
    J --> K[RemoteModule生成]
    K --> L[RemoteRuntimeModule追加]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | デフォルトshareScope | shareScope未指定時は"default"を使用 | ContainerPlugin/ContainerReferencePlugin |
| BR-02 | デフォルトライブラリ | library未指定時は{type:"var", name:options.name}をデフォルト使用 | ContainerPlugin |
| BR-03 | 外部参照キー形式 | リモート外部参照はwebpack/container/reference/{key}形式のキーで登録 | ContainerReferencePlugin |
| BR-04 | internal prefix | external文字列が"internal "で始まる場合は外部参照登録をスキップ | ContainerReferencePlugin |
| BR-05 | フォールバック | 複数のexternalが指定された場合、FallbackModuleで順次試行 | ContainerReferencePlugin |
| BR-06 | slashコード判定 | リクエストの特定位置が"/"文字コード(47)の場合にリモートリクエストとして検出 | ContainerReferencePlugin.factorize |

### 計算ロジック

リモートモジュール解決: normalModuleFactory.hooks.factorizeでリクエスト文字列を解析し、登録済みリモートキーとの前方一致を検出。一致した場合、残りのパスをinternalRequestとしてRemoteModuleを生成する。

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

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | バリデーションエラー | オプションがスキーマに適合しない | createSchemaValidationでエラー出力 |
| - | ランタイムエラー | リモートコンテナの取得失敗 | FallbackModuleによるフォールバック |

### リトライ仕様

FallbackModuleにより複数のリモートソースを順次試行する。

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

該当なし

## パフォーマンス要件

- リモートコンテナの読み込みは非同期で行われ、メインスレッドをブロックしない
- 共有スコープのinit()は一度だけ実行される

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

- リモートコンテナからのコード実行はクロスオリジンのリスクを伴う
- 信頼できるソースからのリモートエントリのみを使用すること

## 備考

- ContainerEntryModuleはJAVASCRIPT_MODULE_TYPE_DYNAMICとして登録される
- ContainerExposedDependencyにより公開モジュールの依存関係が管理される

---

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

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

### 推奨読解順序

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

コンテナ管理のデータ構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ContainerEntryModule.js | `lib/container/ContainerEntryModule.js` | 40-45行目: ExposeOptions型（import, name）とExposesList型 |
| 1-2 | RemoteModule.js | `lib/container/RemoteModule.js` | 42-67行目: request, externalRequests, internalRequest, shareScopeの構造 |
| 1-3 | options.js | `lib/container/options.js` | parseOptionsユーティリティ |

**読解のコツ**: ContainerPluginの"expose"はモジュールを公開する側、ContainerReferencePluginの"remote"は消費する側であり、この非対称な関係を理解することが重要。

#### Step 2: ContainerPlugin（公開側）を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ContainerPlugin.js | `lib/container/ContainerPlugin.js` | 38-63行目: コンストラクタでexposes解析 |
| 2-2 | ContainerPlugin.js | `lib/container/ContainerPlugin.js` | 71-99行目: apply()でのライブラリタイプ有効化とエントリ登録 |
| 2-3 | ContainerEntryModule.js | `lib/container/ContainerEntryModule.js` | 47-77行目: コンテナエントリモジュールの構造 |

**主要処理フロー**:
- **ContainerPlugin 79-98行目**: compilation.addEntryでContainerEntryDependencyを追加
- **ContainerPlugin 82-83行目**: ContainerEntryDependency(name, exposes, shareScope)を生成
- **ContainerPlugin 95行目**: hooks.addContainerEntryDependency.call(dep)

#### Step 3: ContainerReferencePlugin（参照側）を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ContainerReferencePlugin.js | `lib/container/ContainerReferencePlugin.js` | 39-56行目: コンストラクタでremotes解析 |
| 3-2 | ContainerReferencePlugin.js | `lib/container/ContainerReferencePlugin.js` | 63-100行目: apply()での外部参照・ファクトリ登録 |
| 3-3 | RemoteRuntimeModule.js | `lib/container/RemoteRuntimeModule.js` | 19-80行目: リモートモジュール読み込みのランタイムコード生成 |

**主要処理フロー**:
- **ContainerReferencePlugin 67-79行目**: ExternalsPluginでリモート外部参照を登録
- **ContainerReferencePlugin 99-100行目**: factorizeフックでリモートリクエストをRemoteModuleに解決
- **RemoteRuntimeModule 32-61行目**: チャンクごとのリモートマッピングとIDマッピングを生成

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

```
ContainerPlugin.apply(compiler)
    |
    +-- compiler.hooks.make.tapAsync
    |      +-- ContainerEntryDependency(name, exposes, shareScope)
    |      +-- compilation.addEntry()
    |      +-- ContainerEntryModuleFactory
    |             +-- ContainerEntryModule(name, exposes, shareScope)
    |                    +-- ContainerExposedDependency (各expose用)
    |                    +-- StaticExportsDependency
    |
    +-- compilation.hooks.thisCompilation.tap
           +-- ContainerEntryModuleFactory登録

ContainerReferencePlugin.apply(compiler)
    |
    +-- ExternalsPlugin("webpack/container/reference/...")
    |
    +-- compiler.hooks.compilation.tap
           +-- RemoteToExternalDependency ファクトリ登録
           +-- FallbackItemDependency ファクトリ登録
           +-- FallbackDependency → FallbackModuleFactory
           +-- normalModuleFactory.hooks.factorize
           |      +-- RemoteModule(request, externalRequests, internalRequest, shareScope)
           +-- compilation.hooks.runtimeRequirementInTree
                  +-- RemoteRuntimeModule追加
```

### データフロー図

```
[ContainerPlugin - 公開側]
exposes設定 ──> ContainerPlugin ──> ContainerEntryModule ──> remoteEntry.js
                                          |
                                          +-> get(module) → 公開モジュール
                                          +-> init(shareScope) → 共有スコープ初期化

[ContainerReferencePlugin - 参照側]
remotes設定 ──> ContainerReferencePlugin ──> RemoteModule ──> リモートモジュール取得
                      |                          |
                      +-> ExternalsPlugin         +-> RemoteRuntimeModule
                      +-> FallbackModule              (ランタイムコード)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ContainerPlugin.js | `lib/container/ContainerPlugin.js` | ソース | Federationコンテナの作成 |
| ContainerReferencePlugin.js | `lib/container/ContainerReferencePlugin.js` | ソース | リモートコンテナの参照 |
| ContainerEntryModule.js | `lib/container/ContainerEntryModule.js` | ソース | コンテナエントリモジュール |
| ContainerEntryDependency.js | `lib/container/ContainerEntryDependency.js` | ソース | コンテナエントリ依存 |
| ContainerEntryModuleFactory.js | `lib/container/ContainerEntryModuleFactory.js` | ソース | コンテナエントリモジュールファクトリ |
| ContainerExposedDependency.js | `lib/container/ContainerExposedDependency.js` | ソース | 公開モジュール依存 |
| RemoteModule.js | `lib/container/RemoteModule.js` | ソース | リモートモジュール |
| RemoteRuntimeModule.js | `lib/container/RemoteRuntimeModule.js` | ソース | リモート読み込みランタイム |
| RemoteToExternalDependency.js | `lib/container/RemoteToExternalDependency.js` | ソース | リモート→外部参照依存 |
| FallbackModule.js | `lib/container/FallbackModule.js` | ソース | フォールバックモジュール |
| FallbackModuleFactory.js | `lib/container/FallbackModuleFactory.js` | ソース | フォールバックモジュールファクトリ |
| FallbackDependency.js | `lib/container/FallbackDependency.js` | ソース | フォールバック依存 |
| FallbackItemDependency.js | `lib/container/FallbackItemDependency.js` | ソース | フォールバック個別アイテム依存 |
| options.js | `lib/container/options.js` | ソース | オプション解析ユーティリティ |
