# 通知設計書 26-WebAssemblyInInitialChunkError

## 概要

本ドキュメントは、Webpackにおける `WebAssemblyInInitialChunkError` の通知仕様を定義する。WebAssemblyモジュールが初期チャンクに含まれている場合に発行されるエラークラスである。

### 本通知の処理概要

WebAssemblyInInitialChunkErrorは、Webpackのチャンク生成フェーズ（afterChunksフック）において、同期WebAssemblyモジュール（webassembly/sync）が初期チャンクに含まれていることを検出した場合に発行されるエラー通知である。

**業務上の目的・背景**：WebAssemblyモジュールのダウンロードとコンパイルは非同期で行う必要がある。初期チャンクに含まれるとWebAssemblyの読み込みがブロッキングとなり、ブラウザの仕様上の制約に違反する。特に同期WebAssembly（experiments.syncWebAssemblyが有効な場合のレガシーモード）で問題となる。開発者にimport()を使った非同期分割を促すためのエラーである。

**通知の送信タイミング**：compilation.hooks.afterChunksフック実行時（チャンクグラフ構築完了後）に、WebAssemblyModulesPluginが各初期チャンク内のモジュールを検査し、webassembly/sync型のモジュールが見つかった場合に発行される。

**通知の受信者**：Webpackビルドを実行する開発者。compilation.errorsに蓄積されビルドエラーとして表示される。

**通知内容の概要**：WebAssemblyモジュールが初期チャンクに含まれている事実、非同期分割の必要性、エントリーポイントからWebAssemblyモジュールまでのモジュールチェーン（依存関係経路）を表示する。

**期待されるアクション**：開発者は、エントリーポイントとWebAssemblyモジュールの間にdynamic import()（非同期分割ポイント）を挿入し、WebAssemblyモジュールを非同期チャンクに移動させる。

## 通知種別

ビルドエラー（Webpack Compilation Error）。コンソール出力およびStats APIを通じて開発者に通知される。

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（afterChunksフック内で即座に生成） |
| 優先度 | 高（エラーレベル） |
| リトライ | なし（一度きりのエラー発行） |

### 送信先決定ロジック

WebAssemblyModulesPlugin内のcompilation.hooks.afterChunksタップで、初期チャンクに含まれるwebassembly/sync型モジュールを検出し、該当モジュールごとにエラーを生成してcompilation.errorsに直接追加する。

## 通知テンプレート

### メール通知の場合

該当なし。本通知はメール通知ではなく、Webpackビルド出力として表示される。

### 本文テンプレート

```
ERROR in WebAssembly module is included in initial chunk.
This is not allowed, because WebAssembly download and compilation must happen asynchronous.
Add an async split point (i. e. import()) somewhere between your entrypoint and the WebAssembly module:
* {モジュールチェーン1}
* {モジュールチェーン2}
```

### 添付ファイル

該当なし。

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| module | WebAssemblyモジュール | chunkGraph.getChunkModulesIterable() | Yes |
| moduleGraph | モジュール依存関係グラフ | compilation.moduleGraph | Yes |
| chunkGraph | チャンクグラフ | compilation.chunkGraph | Yes |
| requestShortener | パス短縮ユーティリティ | compilation.requestShortener | Yes |
| name | エラー名 | 固定値 "WebAssemblyInInitialChunkError" | Yes |
| hideStack | スタックトレース非表示フラグ | 固定値 true | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| フック実行 | compilation.hooks.afterChunks | 初期チャンク内にwebassembly/sync型モジュールが存在する | WebAssemblyModulesPluginが検査 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| チャンクが初期チャンクでない | chunk.canBeInitial() === false の場合、検査対象外 |
| モジュールがwebassembly/sync型でない | module.type !== WEBASSEMBLY_MODULE_TYPE_SYNC の場合、スキップ |
| 非同期WebAssembly（experiments.asyncWebAssembly） | 非同期WASMモードでは別のプラグインが処理し、このエラーは発行されない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[compilation.hooks.afterChunks発火] --> B[WebAssemblyModulesPlugin処理]
    B --> C[compilation.chunksをループ]
    C --> D{chunk.canBeInitial()?}
    D -->|No| C
    D -->|Yes| E[chunkGraph.getChunkModulesIterableでモジュールをループ]
    E --> F{module.type === webassembly/sync?}
    F -->|No| E
    F -->|Yes| G[initialWasmModules Setに追加]
    G --> E
    E --> H[initialWasmModulesをループ]
    H --> I[getInitialModuleChains でモジュールチェーン算出]
    I --> J[WebAssemblyInInitialChunkError生成]
    J --> K[compilation.errors.push]
    K --> L[終了]
```

## データベース参照・更新仕様

### 参照テーブル一覧

該当なし。Webpackはデータベースを使用しない。

### 更新テーブル一覧

該当なし。

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 循環参照による無限ループ | モジュールチェーン算出時に循環参照がある場合 | visitedModulesで循環検出し "..." プレフィックスを付与して打ち切り |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし |
| リトライ間隔 | 該当なし |
| リトライ対象エラー | 該当なし |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし。ビルド実行時に即座にエラーが生成される。

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

モジュールパス情報がエラーメッセージに含まれるが、ビルド環境内の情報であるためリスクは低い。

## 備考

- WebpackErrorを基底クラスとして継承している
- hideStack = true であるため、スタックトレースは表示されない
- moduleプロパティにWebAssemblyモジュールへの参照を保持
- getInitialModuleChains ヘルパー関数でBFS（幅優先探索）によりエントリーポイントからのモジュールチェーンを算出
- 循環参照を検出した場合は "... -->" プレフィックスを付与してincompleteResultsとして扱う
- connection.explanationがある場合はチェーン内に説明を含める

---

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

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

### 推奨読解順序

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

WebAssemblyInInitialChunkErrorクラスとgetInitialModuleChainsヘルパー関数を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | WebpackError.js | `lib/WebpackError.js` | 基底クラス |
| 1-2 | WebAssemblyInInitialChunkError.js | `lib/wasm-sync/WebAssemblyInInitialChunkError.js` | エラークラス本体。getInitialModuleChains関数（21-83行目）とコンストラクタ（85-111行目） |

**読解のコツ**: getInitialModuleChainsは同一ファイル内のローカル関数で、BFSアルゴリズムでモジュール依存関係を遡る。queueにhead（現在のモジュール）とmessage（チェーン文字列）を保持する構造体を使用する。

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

WebAssemblyModulesPluginのafterChunksフックを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | WebAssemblyModulesPlugin.js | `lib/wasm-sync/WebAssemblyModulesPlugin.js` | 122-145行目でafterChunksフックでの検査ロジック |

**主要処理フロー**:
1. **122行目**: compilation.hooks.afterChunks.tap でフック登録
2. **126行目**: compilation.chunks をループ
3. **127行目**: chunk.canBeInitial() で初期チャンク判定
4. **128行目**: chunkGraph.getChunkModulesIterable(chunk) でモジュール取得
5. **129行目**: module.type === WEBASSEMBLY_MODULE_TYPE_SYNC で型チェック
6. **130行目**: initialWasmModules Set に追加
7. **135-144行目**: 各WASMモジュールに対してエラーを生成しcompilation.errors.push

#### Step 3: モジュールチェーン算出を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | WebAssemblyInInitialChunkError.js | `lib/wasm-sync/WebAssemblyInInitialChunkError.js` | 21-83行目のgetInitialModuleChains関数 |

**主要処理フロー**:
- **27-29行目**: キューを初期化（対象モジュールから開始）
- **37行目**: キューをループ（BFS）
- **42行目**: moduleGraph.getIncomingConnections(head) で逆方向の依存関係取得
- **46行目**: chunkGraph.getModuleChunks(newHead).some(c => c.canBeInitial()) で初期チャンクに含まれるモジュールのみ追跡
- **58-60行目**: visitedModulesで循環検出時は "... -->" を付与
- **67-72行目**: originModuleがnull（エントリーポイント）の場合はresultsに追加

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

```
compilation.hooks.afterChunks
    |
    +-- WebAssemblyModulesPlugin (122行目)
            |
            +-- compilation.chunks ループ (126行目)
            |       |
            |       +-- chunk.canBeInitial() (127行目)
            |       +-- chunkGraph.getChunkModulesIterable(chunk) (128行目)
            |       +-- module.type === WEBASSEMBLY_MODULE_TYPE_SYNC (129行目)
            |
            +-- initialWasmModules ループ (135行目)
                    |
                    +-- getInitialModuleChains(module, moduleGraph, chunkGraph, requestShortener)
                    |       |
                    |       +-- moduleGraph.getIncomingConnections(head) (42行目)
                    |       +-- chunkGraph.getModuleChunks(newHead) (46行目)
                    |       +-- module.readableIdentifier(requestShortener) (28, 53行目)
                    |
                    +-- new WebAssemblyInInitialChunkError(...)
                    |
                    +-- compilation.errors.push(error)
```

### データフロー図

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

compilation.chunks            getChunkModulesIterable()
    |                              |
    +-- canBeInitial() ---------> WASM型モジュール検出 -------> initialWasmModules Set
                                   |                              |
moduleGraph --------------------> getInitialModuleChains()        |
chunkGraph ---------------------> (BFS逆探索)                     v
requestShortener ------------->                          WebAssemblyInInitialChunkError
                                                                  |
                                                                  v
                                                         compilation.errors[]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| WebAssemblyInInitialChunkError.js | `lib/wasm-sync/WebAssemblyInInitialChunkError.js` | ソース | エラークラス本体およびgetInitialModuleChains関数 |
| WebAssemblyModulesPlugin.js | `lib/wasm-sync/WebAssemblyModulesPlugin.js` | ソース | エラーの生成・発行を行うプラグイン |
| WebpackError.js | `lib/WebpackError.js` | ソース | 基底エラー/警告クラス |
