# 画面設計書 21-MFE-C (Remote)

## 概要

本ドキュメントは、webpack Module Federationサンプルにおけるリモートコンテナ C（MFE-C）の画面設計書である。MFE-Cは、Module Federationアーキテクチャにおいてリモートアプリケーションとして機能し、ComponentおよびComponent2（LazyComponent）をホストアプリケーションに公開するマイクロフロントエンドである。

### 本画面の処理概要

MFE-C (Remote) は、webpack 5のModule Federation機能を利用してマイクロフロントエンドアーキテクチャを実現するリモートコンテナの一つである。本リモートコンテナは2つのReactコンポーネントを外部に公開し、ホストアプリケーション（App Host）から消費される。

**業務上の目的・背景**：マイクロフロントエンドアーキテクチャの実証として、独立してビルド・デプロイ可能なリモートアプリケーションを提供する。MFE-Cはdate-fnsとlodashを利用した2つのコンポーネントを公開し、リモート間での共有モジュール管理（reactのsingleton制約、date-fnsやlodashの共有）のデモンストレーションを行う。各リモートは独立したビルド設定を持ち、コンパイル時の依存関係が存在しないため、チーム間で独立した開発・デプロイサイクルを維持できる。

**画面へのアクセス方法**：MFE-C自体は単独で画面を持たない。ホストアプリケーション（No.19 App Host）がリモートエントリファイル `mfeCCC.js` を読み込み、公開されたコンポーネントを取得することでアクセスされる。具体的には、ホスト側のwebpack設定で `"mfe-c": "mfeCCC@/dist/ccc/mfeCCC.js"` として参照される。

**主要な操作・処理内容**：
1. ContainerPlugin により Federation コンテナを作成し、`./Component` と `./Component2` の2つのモジュールを外部に公開する
2. Component は date-fns の `formatRelative` と `subDays` を使用して相対日付を表示するReactコンポーネントである
3. LazyComponent（Component2）は lodash の `random` を使用してランダムな数値を表示するReactコンポーネントであり、ホスト側で `React.lazy()` による遅延読み込みの対象となる
4. react は singleton 制約付きで共有され、`import: false` 設定により自身のバージョンをバンドルせず、ランタイム時にホストから提供されるバージョンを利用する
5. date-fns と lodash/ はリモート間で共有モジュールとして提供される

**画面遷移**：MFE-Cのコンポーネントは、ホストアプリケーション（App Host）の画面内に埋め込まれて表示される。Component は直接インポートされ、LazyComponent（Component2）は `React.lazy()` + `Suspense` により遅延読み込みされる。

**権限による表示制御**：権限による表示制御は実装されていない。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 37 | ModuleFederationPlugin | 主機能 | リモートCとしてComponentおよびComponent2を外部に公開 |
| 38 | コンテナ管理 | 主機能 | ContainerPluginによるFederationコンテナの作成・モジュール公開 |
| 40 | SharePlugin | 補助機能 | reactをsingleton制約で共有 |
| 41 | 共有モジュール提供・消費 | 補助機能 | ProvideSharedPluginによる共有モジュールの提供 |
| 13 | 動的インポート | 補助機能 | LazyComponent(Component2)の遅延読み込み用動的インポート |

## 画面種別

コンポーネント（リモートマイクロフロントエンド）

## URL/ルーティング

MFE-C自体は独立したURLを持たない。リモートエントリファイルとして `/dist/ccc/mfeCCC.js` が公開され、ホストアプリケーションから参照される。

## 入出力項目

### Component（./Component として公開）

| 項目名 | 入出力 | 型 | 必須 | 説明 |
|--------|--------|-----|------|------|
| locale | 入力（props） | object | 任意 | date-fns の locale オブジェクト。相対日付のフォーマットに使用される |

### LazyComponent / Component2（./Component2 として公開）

| 項目名 | 入出力 | 型 | 必須 | 説明 |
|--------|--------|-----|------|------|
| (なし) | - | - | - | props を受け取らない |

## 表示項目

### Component

| 表示項目 | データソース | 表示形式 | 説明 |
|----------|-------------|----------|------|
| コンテナ識別メッセージ | 固定文字列 | テキスト | "I'm a Component exposed from container C!" |
| 相対日付 | date-fns 演算結果 | テキスト | 現在日付の3日前を相対日付形式でフォーマットして表示 |

### LazyComponent（Component2）

| 表示項目 | データソース | 表示形式 | 説明 |
|----------|-------------|----------|------|
| コンテナ識別メッセージ | 固定文字列 | テキスト | "I'm a lazy Component exposed from container C!" |
| 遅延読み込み説明 | 固定文字列 | テキスト | "I'm lazy loaded by the app and lazy load another component myself." |
| ランダム数値 | lodash/random 演算結果 | テキスト | 0から6の範囲のランダム整数を表示 |

## イベント仕様

### 1-コンポーネント読み込み（Component）

ホストアプリケーションが `import ComponentC from "mfe-c/Component"` を実行すると、Module Federationランタイムが以下の処理を行う。

1. リモートエントリファイル `mfeCCC.js` が読み込まれていない場合、スクリプトをロードする
2. ContainerReferencePlugin が `./Component` の公開モジュールを解決する
3. 共有モジュール（react, date-fns）の初期化が行われ、singleton制約に基づきバージョンが解決される
4. Component が返され、ホスト側の React ツリーにレンダリングされる

### 2-遅延コンポーネント読み込み（LazyComponent / Component2）

ホストアプリケーションが `React.lazy(() => import("mfe-c/Component2"))` で遅延読み込みを行う。

1. `React.Suspense` のfallback（"Lazy loading component..."）が表示される
2. `import("mfe-c/Component2")` によりリモートコンテナから `./Component2` が非同期で解決される
3. 共有モジュール（lodash/random）が解決・読み込まれる
4. LazyComponent がレンダリングされ、fallbackが置き換えられる

## データベース更新仕様

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

本画面にデータベース操作は存在しない。

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|--------------|----------|
| - | 情報 | "I'm a Component exposed from container C!" | Component 表示時 |
| - | 情報 | "Using date-fn in Remote: {相対日付}" | Component 表示時 |
| - | 情報 | "I'm a lazy Component exposed from container C!" | LazyComponent 表示時 |
| - | 情報 | "I'm lazy loaded by the app and lazy load another component myself." | LazyComponent 表示時 |
| - | 情報 | "Using lodash in Remote: {ランダム数値}" | LazyComponent 表示時 |

## 例外処理

| 例外 | 発生条件 | 対応 |
|------|----------|------|
| 共有モジュール不在エラー | react の singleton 共有で `import: false` に設定されているため、ランタイム時に有効な共有reactモジュールが存在しない場合 | ランタイムエラーが発生する。ホストアプリケーションがreactを共有モジュールとして提供している必要がある |
| リモートエントリ読み込み失敗 | ネットワークエラー等で `mfeCCC.js` が読み込めない場合 | コンポーネントのレンダリングに失敗する |
| 遅延読み込みタイムアウト | LazyComponent のチャンク読み込みが失敗した場合 | `React.Suspense` の fallback が表示され続ける |

## 備考

- MFE-C の react 共有設定は `import: false` となっており、自身のバージョンをバンドルしない。これによりビルド時間の短縮が実現されるが、ランタイム時に有効な共有 react モジュールが存在しない場合はエラーとなる
- date-fns は MFE-B との間でも共有されている（ホストアプリケーションは date-fns を直接には共有設定していない）
- lodash は `"lodash/"` というパスプレフィックス指定により、lodash 配下の使用されるすべてのモジュールが共有対象となる
- 各ビルドは独立しており、コンパイル時の依存関係はない。`uniqueName: "module-federation-ccc"` によりランタイムでの衝突が回避される

---

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

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

### 推奨読解順序

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

MFE-C が公開する2つのコンポーネントのインターフェースと、共有モジュールの依存関係を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Component.js | `examples/module-federation/src-c/Component.js` | 公開コンポーネントの props インターフェース（locale）と date-fns 依存を確認 |
| 1-2 | LazyComponent.js | `examples/module-federation/src-c/LazyComponent.js` | 遅延読み込み対象のコンポーネント。lodash/random 依存を確認 |

**読解のコツ**: React の関数コンポーネント（アロー関数形式）で、JSX を返す。props の分割代入パターンに注目。

#### Step 2: エントリーポイントを理解する（webpack設定）

Module Federation の設定を理解し、何がどのように公開されるかを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | webpack.config.js | `examples/module-federation/webpack.config.js` | 3つ目の設定オブジェクト（name: "mfe-c"、117-156行目）がMFE-Cの設定。exposes と shared の定義を確認 |

**主要処理フロー**:
1. **117-118行目**: name: "mfe-c" でビルド名を定義
2. **122-124行目**: 出力先を `dist/ccc/` に設定し、publicPath と uniqueName を定義
3. **130行目**: ModuleFederationPlugin でコンテナ名 "mfeCCC" を設定
4. **133-135行目**: `./Component` と `./Component2` を exposes で公開
5. **138-151行目**: lodash/, date-fns, react を共有モジュールとして設定。react は import: false, singleton: true

#### Step 3: ホストアプリケーションとの連携を理解する

ホスト側がどのようにMFE-Cのコンポーネントを消費するかを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | index.js | `examples/module-federation/src/index.js` | 非同期境界として `import("./bootstrap")` を実行。共有モジュール初期化のために必要 |
| 3-2 | bootstrap.js | `examples/module-federation/src/bootstrap.js` | ReactDom.render でアプリケーションをマウント |
| 3-3 | App.js | `examples/module-federation/src/App.js` | MFE-Cのコンポーネントを `import ComponentC from "mfe-c/Component"` で直接インポートし、`React.lazy(() => import("mfe-c/Component2"))` で遅延インポートしている |

**主要処理フロー**:
- **App.js 3行目**: `import ComponentC from "mfe-c/Component"` で Component を同期的にインポート
- **App.js 7行目**: `React.lazy(() => import("mfe-c/Component2"))` で LazyComponent を遅延インポート
- **App.js 17行目**: `<ComponentC locale={de} />` で Component をレンダリング（locale に de を渡す）
- **App.js 18-22行目**: `<React.Suspense>` で LazyComponent をラップし、遅延読み込み中のfallbackを定義

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

```
webpack.config.js (mfe-c設定)
    │
    ├─ ModuleFederationPlugin
    │      ├─ ContainerPlugin (コンテナ作成)
    │      │      ├─ exposes: ./Component → src-c/Component.js
    │      │      └─ exposes: ./Component2 → src-c/LazyComponent.js
    │      │
    │      ├─ ProvideSharedPlugin (共有モジュール提供)
    │      │      ├─ lodash/ (パスプレフィックス共有)
    │      │      ├─ date-fns
    │      │      └─ react (singleton, import: false)
    │      │
    │      └─ ConsumeSharedPlugin (共有モジュール消費)
    │
    ├─ src-c/Component.js
    │      ├─ react (共有)
    │      ├─ date-fns/formatRelative
    │      └─ date-fns/subDays
    │
    └─ src-c/LazyComponent.js
           ├─ react (共有)
           └─ lodash/random (共有)
```

### データフロー図

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

ホストアプリケーション
  │
  ├─ remoteEntry読み込み ───▶ mfeCCC.js (コンテナ初期化) ───▶ コンテナスコープ登録
  │
  ├─ import "mfe-c/     ───▶ ContainerPlugin             ───▶ Component.js
  │   Component"               (モジュール解決)                  │
  │                                                            ├─ date-fns演算
  │                                                            └─ JSX レンダリング
  │
  └─ import("mfe-c/     ───▶ ContainerPlugin             ───▶ LazyComponent.js
      Component2")             (非同期モジュール解決)              │
       (React.lazy)                                            ├─ lodash/random演算
                                                               └─ JSX レンダリング
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Component.js | `examples/module-federation/src-c/Component.js` | ソース | 公開コンポーネント。date-fns使用の相対日付表示 |
| LazyComponent.js | `examples/module-federation/src-c/LazyComponent.js` | ソース | 遅延読み込み用公開コンポーネント。lodash使用のランダム数表示 |
| webpack.config.js | `examples/module-federation/webpack.config.js` | 設定 | MFE-Cを含む3つのビルド設定（mfe-cは117-156行目） |
| App.js | `examples/module-federation/src/App.js` | ソース | ホスト側のアプリケーションコンポーネント。MFE-Cのコンポーネントを消費 |
| index.js | `examples/module-federation/src/index.js` | ソース | ホスト側エントリポイント。非同期境界の確立 |
| bootstrap.js | `examples/module-federation/src/bootstrap.js` | ソース | ホスト側ブートストラップ。React アプリケーションのマウント |
| Component.js (src-b) | `examples/module-federation/src-b/Component.js` | ソース | MFE-B のコンポーネント。date-fns を MFE-C と共有 |
