# 機能設計書 62-IgnorePlugin

## 概要

本ドキュメントは、webpackの組込みプラグインである `IgnorePlugin` の機能設計を記述する。`IgnorePlugin` は、指定パターンに一致するモジュールをバンドルから除外するプラグインである。

### 本機能の処理概要

IgnorePluginは、正規表現パターンまたはカスタム関数を使用して、特定のモジュールリクエストをバンドルプロセスから除外する機能を提供する。NormalModuleFactoryおよびContextModuleFactoryの `beforeResolve` フックにタップし、条件に合致するモジュール解決を阻止する。

**業務上の目的・背景**：大規模なライブラリ（例：momentjsのロケールファイル）を使用する際、不要な部分モジュールがバンドルに含まれることでバンドルサイズが肥大化する問題がある。IgnorePluginはこのようなケースでバンドルサイズを削減し、アプリケーションのパフォーマンスを向上させるために使用される。

**機能の利用シーン**：momentjsの不要なロケールファイルの除外、テスト用モジュールの本番ビルドからの除外、特定のコンテキストに依存するモジュールの選択的除外などに利用される。

**主要な処理内容**：
1. コンストラクタでオプションのスキーマバリデーションを実施する
2. `resourceRegExp`（および任意の`contextRegExp`）によるパターンマッチング、または `checkResource` 関数によるカスタムフィルタリングを行う
3. NormalModuleFactoryの `beforeResolve` フックでモジュール解決を阻止する
4. ContextModuleFactoryの `beforeResolve` フックでコンテキストモジュール解決を阻止する
5. エントリポイントが無視対象の場合、空の `RawModule` に置き換える

**関連システム・外部連携**：NormalModuleFactory、ContextModuleFactory、RawModule、EntryDependencyと連携する。

**権限による制御**：権限による制御は存在しない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能に直接関連する画面はない |

## 機能種別

バリデーション / フィルタリング（モジュール除外）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| resourceRegExp | `RegExp` | No* | リクエスト文字列に対するマッチ正規表現 | checkResourceと排他 |
| contextRegExp | `RegExp` | No | コンテキストパスに対するマッチ正規表現 | resourceRegExpと併用 |
| checkResource | `(resource: string, context: string) => boolean` | No* | カスタムフィルタ関数。trueを返すと無視される | resourceRegExpと排他 |

*注: `resourceRegExp` または `checkResource` のいずれかが必須

### 入力データソース

- webpack設定ファイル（`webpack.config.js`）のpluginsセクション
- モジュール解決時のリクエスト文字列とコンテキストパス

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | `false \| undefined` | falseの場合モジュール解決を中止、undefinedの場合は通常処理を継続 |
| ignoredModule | `RawModule` | エントリポイントが無視対象の場合に設定される空モジュール |

### 出力先

NormalModuleFactoryおよびContextModuleFactoryの `beforeResolve` フックの戻り値として作用し、モジュール解決プロセスに影響を与える。

## 処理フロー

### 処理シーケンス

```
1. apply()でNormalModuleFactoryフックにタップ
   └─ normalModuleFactory.hooks.beforeResolveに登録
2. apply()でContextModuleFactoryフックにタップ
   └─ contextModuleFactory.hooks.beforeResolveに登録
3. モジュール解決リクエスト時にcheckIgnoreが呼ばれる
   └─ checkResource関数またはresourceRegExpでリクエストを検査
4. contextRegExpが指定されている場合、コンテキストも検査
   └─ resourceRegExpとcontextRegExpの両方が一致した場合のみ無視
5. エントリポイントが無視対象の場合
   └─ 空のRawModuleを生成し、ignoredModuleとして設定
```

### フローチャート

```mermaid
flowchart TD
    A[モジュール解決リクエスト] --> B{checkResource が定義?}
    B -->|Yes| C{checkResource が true を返す?}
    C -->|Yes| D[return false - 無視]
    C -->|No| E[次の検査へ]
    B -->|No| E
    E --> F{resourceRegExp がマッチ?}
    F -->|No| G[return undefined - 通常処理]
    F -->|Yes| H{contextRegExp が定義?}
    H -->|No| D
    H -->|Yes| I{contextRegExp がマッチ?}
    I -->|Yes| D
    I -->|No| G
    D --> J{エントリ依存?}
    J -->|Yes| K[空のRawModuleを設定]
    J -->|No| L[モジュール解決を中止]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 正規表現マッチ | resourceRegExpがリクエスト文字列に一致した場合にモジュールを除外 | resourceRegExpが指定されている場合 |
| BR-02 | コンテキスト条件 | contextRegExpが指定されている場合、resourceRegExpとcontextRegExpの両方が一致しないと除外されない | contextRegExpが指定されている場合 |
| BR-03 | カスタム関数 | checkResourceがtrueを返した場合にモジュールを除外 | checkResourceが指定されている場合 |
| BR-04 | エントリポイント保護 | エントリポイントが無視対象の場合、空のRawModuleに置き換えてビルドを継続する | 無視対象がEntryDependencyの場合 |

### 計算ロジック

特筆すべき計算ロジックは存在しない。

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

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

データベース操作は存在しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ValidationError | 設定エラー | オプションがスキーマに適合しない場合 | 正しいオプション形式で指定する |

### リトライ仕様

リトライ仕様は存在しない。

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

トランザクション仕様は存在しない。

## パフォーマンス要件

各モジュール解決リクエストに対して正規表現テストが実行されるため、パターンが複雑な場合はモジュール数に比例したオーバーヘッドが発生する可能性がある。ただし、正規表現テストは高速であり、通常は問題にならない。

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

- 意図しないモジュールが除外されないよう、正規表現パターンを正確に指定する必要がある
- 過度に広範なパターンは、必要なモジュールまで除外してしまうリスクがある

## 備考

- IgnorePluginの典型的なユースケースは `new webpack.IgnorePlugin({ resourceRegExp: /^\.\/locale$/, contextRegExp: /moment$/ })` によるmomentjsロケール除外
- エントリポイントが無視された場合、空のモジュールとして処理される（`sideEffectFree: true`が設定される）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | IgnorePlugin.js | `lib/IgnorePlugin.js` | `options`プロパティ（`resourceRegExp`, `contextRegExp`, `checkResource`）の構造 |

**読解のコツ**: オプションは `resourceRegExp` + `contextRegExp` パターンと `checkResource` パターンの2種類がある。スキーマバリデーション（17-24行目）で形式が検証される。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | IgnorePlugin.js | `lib/IgnorePlugin.js` | `apply()` メソッド（76-102行目）がエントリーポイント |

**主要処理フロー**:
1. **77行目**: `compiler.hooks.normalModuleFactory` にタップ
2. **78行目**: `nmf.hooks.beforeResolve` にタップしてcheckIgnoreを呼び出す
3. **81-94行目**: エントリ依存の場合、空のRawModuleをignoredModuleに設定
4. **99-101行目**: `compiler.hooks.contextModuleFactory` にタップし、checkIgnoreを直接登録

#### Step 3: 無視判定ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | IgnorePlugin.js | `lib/IgnorePlugin.js` | `checkIgnore()` メソッド（45-69行目） |

**主要処理フロー**:
- **46-52行目**: checkResource関数によるカスタム判定
- **54-68行目**: resourceRegExpとcontextRegExpによる正規表現判定
- **59-64行目**: contextRegExpが指定されている場合の両方一致チェック

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

```
IgnorePlugin.apply(compiler)
    |
    +-- compiler.hooks.normalModuleFactory.tap()
    |       |
    |       +-- nmf.hooks.beforeResolve.tap()
    |               |
    |               +-- checkIgnore(resolveData)
    |               |       |
    |               |       +-- checkResource(request, context) [カスタム関数パス]
    |               |       +-- resourceRegExp.test(request) [正規表現パス]
    |               |       +-- contextRegExp.test(context) [コンテキスト正規表現パス]
    |               |
    |               +-- [エントリ依存の場合] new RawModule("", "ignored-entry-module")
    |
    +-- compiler.hooks.contextModuleFactory.tap()
            |
            +-- cmf.hooks.beforeResolve.tap(checkIgnore)
```

### データフロー図

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

resolveData.request ──┐
                      ├──▶ checkIgnore() ──▶ false (無視)
resolveData.context ──┘    (パターンマッチ)      または
                                                undefined (通常処理)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| IgnorePlugin.js | `lib/IgnorePlugin.js` | ソース | 本機能のメインプラグイン |
| RawModule.js | `lib/RawModule.js` | ソース | 無視されたエントリポイントの代替となる空モジュール |
| EntryDependency.js | `lib/dependencies/EntryDependency.js` | ソース | エントリポイント判定に使用 |
| IgnorePlugin.json | `schemas/plugins/IgnorePlugin.json` | 設定 | オプションのバリデーションスキーマ |
