# 機能設計書 7-リゾルバ

## 概要

本ドキュメントは、enhanced-resolveを利用しモジュールパスの解決・エイリアス処理を行うリゾルバ機能の設計を記述する。

### 本機能の処理概要

リゾルバは、モジュールリクエスト文字列（相対パス、パッケージ名等）を絶対ファイルパスに解決する機能である。ResolverFactoryがリゾルバインスタンスの生成・キャッシュを管理し、enhanced-resolveライブラリに解決処理を委譲する。リゾルバは「normal」「context」「loader」の3種類があり、それぞれモジュール、ディレクトリ、ローダーの解決に使用される。

**業務上の目的・背景**：モジュールバンドリングでは、import/requireで指定されたパスを実際のファイルパスに解決する必要がある。Node.jsの標準的なモジュール解決アルゴリズムに加え、エイリアス、拡張子自動補完、package.jsonのexportsフィールド対応等の高度な解決機能が求められる。

**機能の利用シーン**：NormalModuleFactory内でモジュールパスを解決する際、およびローダーパスを解決する際に使用される。すべてのモジュール参照の解決に関わる基盤機能である。

**主要な処理内容**：
1. ResolverFactory.get()によるリゾルバインスタンスの取得（キャッシュ付き）
2. ResolverFactory._create()によるenhanced-resolve.ResolverFactory.createResolver()の呼び出し
3. resolveOptionsフックによるリゾルバオプションのカスタマイズ
4. resolverフックによる生成後のリゾルバのカスタマイズ
5. withOptions()によるオプション差分付きリゾルバの派生

**関連システム・外部連携**：enhanced-resolve（外部パッケージ）、cleverMerge（オプションマージユーティリティ）と連携する。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | リゾルバは画面に直接関連しない基盤機能。全モジュール参照の解決に使用される |

## 機能種別

パス解決 / キャッシュ管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| type | string | Yes | リゾルバの種類（"normal", "context", "loader"） | 有効なタイプであること |
| resolveOptions | ResolveOptionsWithDependencyType | No | 解決オプション（エイリアス、拡張子等） | - |

### 入力データソース

- webpack.config.jsのresolve設定
- 各依存関係のdependencyType

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| resolver | ResolverWithOptions | 設定済みリゾルバインスタンス |

### 出力先

- NormalModuleFactoryに渡され、モジュールパス解決に使用される

## 処理フロー

### 処理シーケンス

```
1. ResolverFactory.get(type, resolveOptions) 呼び出し
   ├─ WeakMapキャッシュの確認（直接参照）
   ├─ StringifiedMapキャッシュの確認（JSON文字列化キー）
   └─ キャッシュミス時: _create()呼び出し
2. _create(type, resolveOptionsWithDepType) 実行
   ├─ resolveOptionsフック（HookMap）でオプションをカスタマイズ
   ├─ convertToResolveOptions()でenhanced-resolve形式に変換
   │   ├─ dependencyTypeプロパティの除去
   │   ├─ byDependencyプロパティの解決
   │   └─ pluginsフィルタリング（"..."の除外）
   ├─ enhanced-resolve.ResolverFactory.createResolver()でリゾルバ生成
   ├─ withOptions()メソッドの付与（派生リゾルバ生成用）
   └─ resolverフック呼び出し（生成後カスタマイズ）
3. キャッシュへの登録
```

### フローチャート

```mermaid
flowchart TD
    A[get type resolveOptions] --> B{WeakMapキャッシュ?}
    B -->|Hit| C[キャッシュ済みリゾルバ返却]
    B -->|Miss| D{StringifiedMapキャッシュ?}
    D -->|Hit| E[キャッシュ済みリゾルバ返却+WeakMap登録]
    D -->|Miss| F[_create呼び出し]
    F --> G[resolveOptionsフック]
    G --> H[convertToResolveOptions]
    H --> I[enhanced-resolve.createResolver]
    I --> J[withOptions付与]
    J --> K[resolverフック]
    K --> L[キャッシュ登録]
    L --> M[リゾルバ返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 2段階キャッシュ | WeakMap（オブジェクト参照）とMap（文字列化キー）の2段階でキャッシュ | get()呼び出し時 |
| BR-02 | byDependency解決 | resolveオプションのbyDependencyフィールドをdependencyTypeに基づき解決 | dependencyTypeが指定されている場合 |
| BR-03 | fileSystem必須 | resolveOptionsにfileSystemがない場合はエラー | convertToResolveOptions内 |
| BR-04 | withOptions派生 | withOptions()で差分オプション付きの新リゾルバを生成可能 | リゾルバ利用時 |

### 計算ロジック

特になし。

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

該当なし。

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

該当なし。

### テーブル別操作詳細

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| Error("fileSystem is missing") | 設定エラー | resolveOptionsにfileSystemがない | fileSystemを設定する |
| Error("No resolver created") | 生成エラー | enhanced-resolveがリゾルバを生成できない | resolve設定を確認 |

### リトライ仕様

リトライ機構はない。

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

該当なし。

## パフォーマンス要件

- 2段階キャッシュ（WeakMap + Map）により同一オプションのリゾルバ再生成を防止
- withOptions()のキャッシュにより派生リゾルバの再生成を防止
- enhanced-resolve自体にも内部キャッシュがある

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

特になし。

## 備考

- enhanced-resolveはwebpackと同じ開発者による外部パッケージ
- resolve設定のbyDependencyフィールドにより、依存タイプ（esm, commonjs等）ごとに異なる解決ルールを適用可能

---

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

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

### 推奨読解順序

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

ResolverFactoryの型定義とキャッシュ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ResolverFactory.js | `lib/ResolverFactory.js` | ResolveOptionsWithDependencyType/ResolverWithOptions/ResolverCache型定義（21-75行目）を理解する |

**読解のコツ**: ResolverWithOptionsはResolver & WithOptionsの交差型。withOptions()メソッドを持つことで、差分オプション付きのリゾルバ派生が可能。

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

ResolverFactory.get()がリゾルバ取得の起点。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ResolverFactory.js | `lib/ResolverFactory.js` | get()メソッド（98-121行目）で2段階キャッシュとリゾルバ取得フローを理解する |

**主要処理フロー**:
1. **99-106行目**: typedCachesの取得・初期化（WeakMap + Map）
2. **107-109行目**: WeakMapからの直接キャッシュルックアップ
3. **111-116行目**: JSON文字列化によるMapキャッシュルックアップ
4. **117-120行目**: キャッシュミス時の_create()呼び出しと両キャッシュへの登録

#### Step 3: リゾルバ生成を理解する

_create()メソッドの内部処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ResolverFactory.js | `lib/ResolverFactory.js` | _create()メソッド（128-155行目）でオプション変換→リゾルバ生成→フック呼び出しの流れを理解する |
| 3-2 | ResolverFactory.js | `lib/ResolverFactory.js` | convertToResolveOptions()関数（37-69行目）でオプション変換ロジックを理解する |

**主要処理フロー**:
- **132-133行目**: resolveOptionsフックでオプションをカスタマイズ後、convertToResolveOptions()で変換
- **135-137行目**: enhanced-resolve.ResolverFactory.createResolver()でリゾルバ生成
- **143-150行目**: withOptions()メソッドの付与。cachedCleverMergeでオプションをマージ
- **151-153行目**: resolverフックでリゾルバをカスタマイズ

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

```
ResolverFactory.get(type, resolveOptions)
    │
    ├─ キャッシュ確認（WeakMap → Map）
    │
    └─ _create(type, resolveOptionsWithDepType)
           ├─ hooks.resolveOptions.for(type).call()
           ├─ convertToResolveOptions()
           │      ├─ dependencyType除去
           │      ├─ byDependency解決（resolveByProperty）
           │      ├─ plugins "..." フィルタリング
           │      └─ unsafeCache保持（removeOperations）
           ├─ enhanced-resolve.ResolverFactory.createResolver()
           ├─ resolver.withOptions = (options) => { ... }
           └─ hooks.resolver.for(type).call()
```

### データフロー図

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

type + resolveOptions ──▶ ResolverFactory.get()
                                │
webpack resolve設定 ────▶ resolveOptionsフック ──▶ カスタマイズ済みオプション
                                │
                         convertToResolveOptions() ──▶ enhanced-resolve形式
                                │
                         createResolver() ──────────▶ Resolverインスタンス
                                │
                         resolverフック ─────────────▶ カスタマイズ済みResolver
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ResolverFactory.js | `lib/ResolverFactory.js` | ソース | リゾルバファクトリ本体（157行） |
| cleverMerge.js | `lib/util/cleverMerge.js` | ソース | オプションマージユーティリティ |
| enhanced-resolve | `node_modules/enhanced-resolve/` | 外部依存 | 実際のパス解決エンジン |
