# 機能設計書 48-WebWorkerチャンクローディング

## 概要

本ドキュメントは、Web Worker環境向けのimportScripts方式チャンク読み込み機能について、ImportScriptsChunkLoadingPluginおよびImportScriptsChunkLoadingRuntimeModuleを中心に設計内容を記述する。

### 本機能の処理概要

本機能は、Web Worker環境においてimportScripts()を使用してチャンクを同期的に読み込むランタイムコードを生成する。Web Workerのグローバルスコープで利用可能なimportScripts APIを活用し、JSONP方式と同様のchunkLoadingGlobalによるデータ受信パターンを採用する。

**業務上の目的・背景**：Web Worker環境ではDOM操作(scriptタグの挿入)が利用できないため、ブラウザ向けのJSONP方式は使用できない。代わりにWeb Worker APIのimportScripts()を使用してスクリプトを同期的に読み込む必要がある。

**機能の利用シーン**：webpack設定の`output.chunkLoading`が`import-scripts`の場合に使用される。Web Workerターゲットのビルドで自動的に選択される。

**主要な処理内容**：
1. ImportScriptsChunkLoadingPlugin: chunkLoading === "import-scripts" の場合にランタイムモジュールを登録
2. ImportScriptsChunkLoadingRuntimeModule: importScripts()によるチャンク読み込みランタイムコード生成
3. installChunk関数でチャンクデータ(chunkIds, moreModules, runtime)を処理
4. chunkLoadingGlobal.pushの上書きによるチャンク受信コールバック

**関連システム・外部連携**：StartupChunkDependenciesPlugin(起動チャンク依存関係、asyncChunkLoading: true)

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面との直接的な関連なし（Web Worker環境向け内部機構） |

## 機能種別

ランタイムコード生成

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| chunkId | ChunkId | Yes | 読み込むチャンクのID | - |
| promises | Promise[] | Yes | チャンク読み込みPromiseの配列 | - |

### 入力データソース

- __webpack_require__.e(chunkId)経由のチャンク読み込みリクエスト

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ランタイムコード | string | importScripts読み込みのJavaScriptランタイムコード |

### 出力先

- webpackランタイムバンドル内

## 処理フロー

### 処理シーケンス

```
1. ImportScriptsChunkLoadingPlugin.apply()
   +-- chunkLoading === "import-scripts" の場合に有効化
   +-- StartupChunkDependenciesPlugin(asyncChunkLoading: true)を適用
   +-- runtimeRequirementInTreeフックに登録

2. ensureChunkHandlers.i (チャンク読み込み)
   +-- installedChunks確認 (1 = loaded)
   +-- importScripts(publicPath + getChunkScriptFilename(chunkId)) で同期読み込み

3. installChunk (チャンクインストール)
   +-- [chunkIds, moreModules, runtime] を分割代入
   +-- moduleFactoriesにモジュール登録
   +-- runtime実行
   +-- installedChunks[chunkId] = 1 でロード済みマーク
   +-- parentChunkLoadingFunction(data) で元のpush呼び出し

4. chunkLoadingGlobal.pushの上書き
   +-- 元のpushをparentChunkLoadingFunctionとして保持
   +-- chunkLoadingGlobal.push = installChunk に置換
```

### フローチャート

```mermaid
flowchart TD
    A[import呼び出し] --> B[__webpack_require__.e]
    B --> C[ensureChunkHandlers.i]
    C --> D{installedChunks状態?}
    D -->|1: loaded| E[完了]
    D -->|undefined: not loaded| F[importScriptsで読み込み]
    F --> G[installChunk]
    G --> H[moduleFactories登録]
    H --> I[runtime実行]
    I --> J[installedChunks = 1]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-48-01 | 同期読み込み | importScripts()は同期的にスクリプトを実行する | 常時 |
| BR-48-02 | チャンク状態 | 1=loaded、それ以外=未ロード | 常時 |
| BR-48-03 | push上書き | chunkLoadingGlobal.pushをinstallChunkに置換 | withCallback又はwithLoading時 |
| BR-48-04 | baseURI | self.locationからbaseURIを算出 | baseURI未指定時 |
| BR-48-05 | Trusted Types | trustedTypes設定時にcreateScriptUrlを使用 | trustedTypes有効時 |

### 計算ロジック

- baseURI: `self.location + "/../" + rootOutputDir` で算出(rootOutputDirはgetUndoPathで算出)

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | Error | HMR更新チャンクの読み込み失敗(success=false) | "Loading update chunk failed for unknown reason"エラーを投げる |

### リトライ仕様

リトライは行わない。

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

該当なし

## パフォーマンス要件

- importScripts()は同期呼び出しのためWorkerスレッドをブロックする
- StartupChunkDependenciesPluginのasyncChunkLoading=trueにより、起動チャンクはPromise.allで並列読み込み

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

- trustedTypes設定時にはcreateScriptUrlを使用してURLをサニタイズ
- HMRマニフェストのfetch時にresponse.okチェックを実施

## 備考

- Web Worker環境ではDOMアクセス不可のため、Prefetch/Preloadの機能はサポートされない
- installedChunksの状態値はJSONP方式の0ではなく1(loaded)を使用
- HMRマニフェスト取得にはfetch APIを使用(Web Workerでfetchが利用可能な前提)

---

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

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

### 推奨読解順序

#### Step 1: プラグイン登録を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ImportScriptsChunkLoadingPlugin.js | `lib/webworker/ImportScriptsChunkLoadingPlugin.js` | **24-107行目**: apply()全体。StartupChunkDependenciesPluginの適用とruntimeRequirementInTreeフックへの登録 |
| 1-2 | ImportScriptsChunkLoadingPlugin.js | `lib/webworker/ImportScriptsChunkLoadingPlugin.js` | **25-28行目**: StartupChunkDependenciesPlugin(asyncChunkLoading: true)の適用 |
| 1-3 | ImportScriptsChunkLoadingPlugin.js | `lib/webworker/ImportScriptsChunkLoadingPlugin.js` | **35-41行目**: isEnabledForChunk判定(chunkLoading === "import-scripts") |
| 1-4 | ImportScriptsChunkLoadingPlugin.js | `lib/webworker/ImportScriptsChunkLoadingPlugin.js` | **53-55行目**: trustedTypes設定時のwithCreateScriptUrlフラグ |

#### Step 2: ランタイムコード生成を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ImportScriptsChunkLoadingRuntimeModule.js | `lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js` | **31-37行目**: コンストラクタ。STAGE_ATTACHステージで登録 |
| 2-2 | ImportScriptsChunkLoadingRuntimeModule.js | `lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js` | **44-65行目**: _generateBaseUri()。self.locationベースのbaseURI生成 |
| 2-3 | ImportScriptsChunkLoadingRuntimeModule.js | `lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js` | **70-228行目**: generate()メソッド全体 |

**主要処理フロー**:
- **108-116行目**: installedChunksの初期化(1 = loaded)
- **121-139行目**: installChunk関数。chunkIds/moreModules/runtimeの分割代入、moduleFactories登録、installedChunks更新
- **145-167行目**: ensureChunkHandlers.i。importScripts()による同期チャンク読み込み
- **170-172行目**: chunkLoadingGlobal.pushのinstallChunkへの置換
- **176-208行目**: HMR loadUpdateChunk関数。hotUpdateGlobal経由で更新モジュール受信
- **211-226行目**: HMRマニフェスト取得。fetch APIでマニフェストJSON取得

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

```
ImportScriptsChunkLoadingPlugin.apply(compiler)
    |
    +-- StartupChunkDependenciesPlugin.apply(compiler)
    |       +-- asyncChunkLoading: true
    |
    +-- compilation.hooks.runtimeRequirementInTree
    |       +-- for(ensureChunkHandlers)
    |       +-- for(hmrDownloadUpdateHandlers)
    |       +-- for(hmrDownloadManifest)
    |       +-- for(baseURI)
    |       +-- for(onChunksLoaded)
    |               +-- handler()
    |                       +-- compilation.addRuntimeModule(ImportScriptsChunkLoadingRuntimeModule)
    |
    +-- compilation.hooks.runtimeRequirementInTree (追加依存)
            +-- ensureChunkHandlers -> publicPath, getChunkScriptFilename
            +-- hmrDownloadUpdateHandlers -> publicPath, getChunkUpdateScriptFilename, moduleCache, hmrModuleData, moduleFactoriesAddOnly
            +-- hmrDownloadManifest -> publicPath, getUpdateManifestFilename

ImportScriptsChunkLoadingRuntimeModule.generate()
    +-- _generateBaseUri() -> baseURI = self.location + rootOutputDir
    +-- installedChunks初期化
    +-- installChunk関数
    +-- ensureChunkHandlers.i -> importScripts()
    +-- chunkLoadingGlobal.push上書き
    +-- [HMR] loadUpdateChunk -> importScripts() + hotUpdateGlobal
    +-- [HMR] hmrDownloadManifest -> fetch()
```

### データフロー図

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

chunkId          ----->  ensureChunkHandlers.i            ----->  void (同期完了)
                         +-- installedChunks確認
                         +-- importScripts(publicPath + filename)
                               |
                               v (グローバルスコープ実行)
                         installChunk(data)
                         +-- data[0] (chunkIds配列)
                         +-- data[1] (モジュールファクトリ)
                         +-- data[2] (ランタイムコード)
                               |
                               v
                         moduleFactories登録
                         installedChunks = 1
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ImportScriptsChunkLoadingPlugin.js | `lib/webworker/ImportScriptsChunkLoadingPlugin.js` | ソース | プラグイン登録・有効化判定 |
| ImportScriptsChunkLoadingRuntimeModule.js | `lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js` | ソース | importScripts方式ランタイムコード生成 |
| StartupChunkDependenciesPlugin.js | `lib/runtime/StartupChunkDependenciesPlugin.js` | ソース | 起動チャンク依存関係プラグイン |
| StartupChunkDependenciesRuntimeModule.js | `lib/runtime/StartupChunkDependenciesRuntimeModule.js` | ソース | 起動チャンク依存関係ランタイムモジュール |
