# 画面設計書 14-Page A

## 概要

本ドキュメントは、webpackサンプルプロジェクト「two-explicit-vendor-chunks」に含まれるPage A画面の設計仕様を記載する。明示的なvendorバンドル分離パターンを実証するページであり、vendor1.jsとvendor2.jsの両方に依存するエントリポイントである。

### 本画面の処理概要

Page Aは、two-explicit-vendor-chunksサンプルにおいてSplitChunksPluginの`enforce: true`オプションによる明示的なvendorチャンク分離を実証する画面である。

**業務上の目的・背景**：本画面はwebpackのSplitChunksPluginにおける明示的なvendorチャンク分離パターンを検証するために存在する。通常のSplitChunksPluginはサイズベースの自動分割を行うが、`enforce: true`を設定することでサイズ条件を無視してvendorモジュールを強制的に独立チャンクに分離できることを実証する。pageAはvendor1とvendor2の両方をrequireし、3つのスクリプト（vendor1.js、vendor2.js、pageA.js）が必要となるパターンを示す。

**画面へのアクセス方法**：pageA.htmlを直接ブラウザで開く。HTMLファイルは`vendor1.js` → `vendor2.js` → `pageA.js`の順にスクリプトを読み込む構成となっている。

**主要な操作・処理内容**：
1. pageA.jsが実行され、`module.exports = "pageA"`でページ識別子をエクスポートする
2. `require("./vendor1")`でvendor1モジュールを同期読み込みする
3. `require("./vendor2")`でvendor2モジュールを同期読み込みする
4. vendor2.jsは内部で`require("./vendor1")`を呼び出しており、vendor1への依存関係を持つ

**画面遷移**：pageA.htmlはPage A単独のページ。Page B、Page Cとの明示的な画面遷移は定義されていない。

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

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 12 | SplitChunksPlugin | 主機能 | 明示的なvendorチャンク(vendor1,vendor2)の分離。enforce:trueによる強制分割 |
| 4 | エントリポイント管理 | 主機能 | vendor1,vendor2と共にエントリポイントとして登録 |
| 6 | 依存性解析 | 補助機能 | vendor1,vendor2へのrequire依存関係を解析 |
| 10 | チャンクグラフ構築 | 補助機能 | vendorチャンクとページチャンクの依存グラフ構築 |
| 3 | モジュール処理 | 補助機能 | vendorモジュールおよびページモジュールの解析・変換 |

## 画面種別

エントリポイントページ（モジュールエクスポートのみ）

## URL/ルーティング

- `pageA.html` - Page A表示用

HTMLファイルでのスクリプト読み込み順序：
1. `js/vendor1.js` （vendor1チャンク）
2. `js/vendor2.js` （vendor2チャンク）
3. `js/pageA.js` （Page A固有チャンク）

## 入出力項目

| 項目名 | 種別 | データ型 | 必須 | 説明 |
|--------|------|----------|------|------|
| なし | - | - | - | 本画面はユーザー入力を受け付けない |

## 表示項目

| 項目名 | 種別 | 出力先 | 説明 |
|--------|------|--------|------|
| なし | - | - | 本画面はmodule.exportsで文字列をエクスポートするのみで、画面表示やコンソール出力はない |

## イベント仕様

### 1-ページ読み込み

pageA.jsの実行時、以下の処理が順次実行される：
1. `module.exports = "pageA"` でページ識別子をモジュールとしてエクスポート
2. `require("./vendor1")` でvendor1モジュールを同期読み込み（vendor1は文字列"Vendor1"を返す）
3. `require("./vendor2")` でvendor2モジュールを同期読み込み（vendor2は文字列"Vendor2"を返し、内部でvendor1もrequireする）

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| なし | - | - | 本画面はフロントエンドのみのデモであり、データベース操作は存在しない |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|----------|
| なし | - | - | 本画面にはメッセージ出力は実装されていない |

## 例外処理

| 例外 | 条件 | 動作 |
|------|------|------|
| vendor1.jsロード失敗 | vendor1チャンクファイルが見つからない場合 | vendor2.jsおよびpageA.jsの実行時にrequire解決エラー |
| vendor2.jsロード失敗 | vendor2チャンクファイルが見つからない場合 | pageA.jsの実行時にrequire解決エラー |
| スクリプト読み込み順序不正 | vendor1/vendor2の前にpageA.jsが読み込まれた場合 | モジュール未定義エラー |

## 備考

- vendor1とvendor2はそれぞれ独立したエントリポイントとしてwebpack.config.jsに配列形式（`["./vendor1"]`）で登録されている
- SplitChunksPluginのcacheGroupsで`test: "vendor1"`と`test: "vendor2"`を指定し、`enforce: true`で強制分割
- vendor2.jsはvendor1.jsをrequireしているため、vendor1チャンクに含まれるモジュールとvendor2チャンクの間に依存関係が存在する
- 出力ファイル名は`[name].js`パターンで、エントリ名がそのままファイル名となる

---

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

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

### 推奨読解順序

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

vendorモジュールの構成と依存関係を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | vendor1.js | `examples/two-explicit-vendor-chunks/vendor1.js` | `module.exports = "Vendor1"` で単純な文字列をエクスポート。他のモジュールへの依存なし |
| 1-2 | vendor2.js | `examples/two-explicit-vendor-chunks/vendor2.js` | `module.exports = "Vendor2"` で文字列をエクスポートし、さらに`require("./vendor1")`でvendor1への依存を持つ |

**読解のコツ**: vendor2がvendor1に依存しているため、チャンク分割後もvendor1チャンクがvendor2チャンクより先に読み込まれる必要がある。HTMLでのスクリプト順序がこの依存を反映している。

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

Page Aのエントリーポイントファイルを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | pageA.js | `examples/two-explicit-vendor-chunks/pageA.js` | 行1: "pageA"をエクスポート。行2-3: vendor1とvendor2を同期require。3つのモジュール全てに依存するページ |

**主要処理フロー**:
1. **行1**: `module.exports = "pageA"` - ページ識別子のエクスポート
2. **行2**: `require("./vendor1")` - vendor1モジュールの同期読み込み
3. **行3**: `require("./vendor2")` - vendor2モジュールの同期読み込み

#### Step 3: webpack設定を理解する

SplitChunksPluginのenforce設定による明示的vendorチャンク分離を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | webpack.config.js | `examples/two-explicit-vendor-chunks/webpack.config.js` | 行8-14: 5つのエントリポイント（vendor1, vendor2, pageA, pageB, pageC）を定義。行20-33: vendor1とvendor2のcacheGroupsでenforce:trueによる強制分割 |

**主要処理フロー**:
- **行9-10**: vendor1とvendor2を配列形式でエントリポイント登録
- **行15-17**: output設定で`path`と`filename: "[name].js"`を指定
- **行22-26**: vendor1のcacheGroup: `name: "vendor1"`, `test: "vendor1"`, `enforce: true`
- **行27-31**: vendor2のcacheGroup: `name: "vendor2"`, `test: "vendor2"`, `enforce: true`

#### Step 4: HTMLテンプレートを理解する

ブラウザでの読み込み順序と依存関係を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | pageA.html | `examples/two-explicit-vendor-chunks/pageA.html` | vendor1.js → vendor2.js → pageA.jsの順にロード。vendor間の依存関係を反映した順序 |

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

```
pageA.js [エントリポイント]
    |
    +-- module.exports = "pageA"  [エクスポート]
    |
    +-- require("./vendor1")  [同期読み込み]
    |       |
    |       +-- vendor1.js  -> "Vendor1"
    |
    +-- require("./vendor2")  [同期読み込み]
            |
            +-- vendor2.js  -> "Vendor2"
                    |
                    +-- require("./vendor1")  -> "Vendor1" [再参照]
```

### データフロー図

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

HTMLロード            vendor1.jsチャンク読み込み
(pageA.html) ----->  (vendor1.js含む)
                          |
                     vendor2.jsチャンク読み込み
                     (vendor2.js含む)
                          |
                     pageA.js実行
                          |                            module.exports
                     +----+----+                       = "pageA"
                     |         |
               vendor1     vendor2
               ("Vendor1") ("Vendor2")
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| pageA.js | `examples/two-explicit-vendor-chunks/pageA.js` | ソース | Page Aのエントリポイント。vendor1とvendor2に依存 |
| pageB.js | `examples/two-explicit-vendor-chunks/pageB.js` | ソース | Page B（比較対象） |
| pageC.js | `examples/two-explicit-vendor-chunks/pageC.js` | ソース | Page C（比較対象） |
| vendor1.js | `examples/two-explicit-vendor-chunks/vendor1.js` | ソース | vendor1モジュール |
| vendor2.js | `examples/two-explicit-vendor-chunks/vendor2.js` | ソース | vendor2モジュール。vendor1に依存 |
| webpack.config.js | `examples/two-explicit-vendor-chunks/webpack.config.js` | 設定 | エントリポイントとSplitChunksPlugin設定 |
| pageA.html | `examples/two-explicit-vendor-chunks/pageA.html` | テンプレート | Page A表示用HTML |
