# 帳票設計書 11-Stats プロファイルレポート

## 概要

本ドキュメントは、webpackビルドにおけるモジュールのビルドプロファイル情報（各処理フェーズの所要時間）を構造化して出力する「Stats プロファイルレポート」の設計仕様を定義するものである。

### 本帳票の処理概要

Stats プロファイルレポートは、webpackビルドプロセスにおける個々のモジュールの処理時間を詳細に分解して出力する帳票である。各モジュールが経る「解決（factory）」「復元（restoring）」「ビルド（building）」「統合（integration）」「格納（storing）」の各フェーズにかかった時間をミリ秒単位で計測し、パフォーマンスボトルネックの特定を支援する。

**業務上の目的・背景**：大規模プロジェクトのビルド時間が長大化した際、どのモジュールのどの処理フェーズがボトルネックとなっているかを特定するために本帳票が必要である。モジュール単位の処理時間を可視化することで、ビルド最適化の方針策定に活用できる。

**帳票の利用シーン**：ビルドパフォーマンスの調査・改善時に利用される。`stats.toJson({ profile: true })` または `--profile` オプションを指定したビルド実行後に、各モジュールの `profile` プロパティとして出力される。

**主要な出力内容**：
1. total - 全フェーズの合計時間（factory + restoring + integration + building + storing）
2. resolving（factory） - モジュール解決にかかった時間
3. restoring - キャッシュからの復元にかかった時間
4. building - モジュールのビルド（パース・変換）にかかった時間
5. integration - モジュールグラフへの統合にかかった時間
6. storing - キャッシュへの格納にかかった時間
7. additionalResolving - 追加の解決処理にかかった時間
8. additionalIntegration - 追加の統合処理にかかった時間

**帳票の出力タイミング**：webpackビルド完了後、`Stats.toJson()` または `Stats.toString()` が呼び出された際に、`profile` オプションが有効な場合にモジュール情報の一部として出力される。

**帳票の利用者**：フロントエンド開発者、ビルドエンジニア、パフォーマンスチューニング担当者。

## 帳票種別

統計レポート（ビルドパフォーマンス分析用）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | CLI / API | `webpack --profile --json` | ビルドコマンド実行 |
| - | Node.js API | `stats.toJson({ profile: true })` | API呼び出し |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | JSON（Stats JSONの一部） |
| 用紙サイズ | N/A（データ出力） |
| 向き | N/A |
| ファイル名 | stats.json（Stats JSON全体の一部として出力） |
| 出力方法 | 標準出力 / ファイル出力 / API戻り値 |
| 文字コード | UTF-8 |

## 帳票レイアウト

### レイアウト概要

Stats プロファイルレポートは、Stats JSONのモジュール情報に付随する `profile` オブジェクトとして出力される。各モジュールごとに1つのプロファイルオブジェクトが生成される。

```
StatsCompilation
└── modules[]
    └── profile (StatsProfile)
        ├── total: number
        ├── resolving: number
        ├── restoring: number
        ├── building: number
        ├── integration: number
        ├── storing: number
        ├── additionalResolving: number
        ├── additionalIntegration: number
        ├── factory: number (deprecated alias for resolving)
        └── dependencies: number (deprecated alias for additionalResolving)
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | module.identifier | プロファイル対象モジュールの識別子 | Module.identifier() | 文字列 |
| 2 | module.name | プロファイル対象モジュールの表示名 | Module.readableIdentifier() | 文字列 |

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | total | 全処理フェーズの合計時間 | profile.factory + restoring + integration + building + storing | 数値（ms） | - |
| 2 | resolving | モジュール解決時間 | profile.factory | 数値（ms） | - |
| 3 | restoring | キャッシュ復元時間 | profile.restoring | 数値（ms） | - |
| 4 | building | ビルド処理時間 | profile.building | 数値（ms） | - |
| 5 | integration | 統合処理時間 | profile.integration | 数値（ms） | - |
| 6 | storing | キャッシュ格納時間 | profile.storing | 数値（ms） | - |
| 7 | additionalResolving | 追加解決時間 | profile.additionalFactories | 数値（ms） | - |
| 8 | additionalIntegration | 追加統合時間 | profile.additionalIntegration | 数値（ms） | - |
| 9 | factory | モジュール解決時間（非推奨） | profile.factory | 数値（ms） | - |
| 10 | dependencies | 追加解決時間（非推奨） | profile.additionalFactories | 数値（ms） | - |

### フッター部

該当なし（モジュール単位の出力のため、集計フッターは存在しない）。

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| profileオプション | Stats オプションの `profile` が true であること | Yes |
| モジュールプロファイル存在 | `moduleGraph.getProfile(module)` が null でないこと | Yes |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| - | モジュールの出力順に従う | - |

### 改ページ条件

N/A（JSON出力のため改ページの概念なし）

## データベース参照仕様

### 参照テーブル一覧

本帳票はデータベースを参照せず、webpackの内部データ構造を参照する。

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| ModuleProfile（内部クラス） | モジュール処理時間の計測結果を保持 | moduleGraph.getProfile(module) |
| ModuleGraph（内部クラス） | モジュール間の依存関係グラフ | compilation.moduleGraph |

### テーブル別参照項目詳細

#### ModuleProfile

| 参照項目（プロパティ名） | 帳票項目との対応 | 取得条件 | 備考 |
|-------------------|----------------|---------|------|
| factory | resolving, factory | - | factoryEndTime - factoryStartTime で算出 |
| restoring | restoring | - | restoringEndTime - restoringStartTime で算出 |
| building | building | - | buildingEndTime - buildingStartTime で算出 |
| integration | integration | - | integrationEndTime - integrationStartTime で算出 |
| storing | storing | - | storingEndTime - storingStartTime で算出 |
| additionalFactories | additionalResolving, dependencies | - | mergeInto()で設定 |
| additionalIntegration | additionalIntegration | - | 非推奨フィールド |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| total | factory + restoring + integration + building + storing | なし（整数ms） | 全フェーズの合計 |
| factory | factoryEndTime - factoryStartTime | なし | Date.now()差分 |
| restoring | restoringEndTime - restoringStartTime | なし | Date.now()差分 |
| building | buildingEndTime - buildingStartTime | なし | Date.now()差分 |
| integration | integrationEndTime - integrationStartTime | なし | Date.now()差分 |
| storing | storingEndTime - storingStartTime | なし | Date.now()差分 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[Stats.toJson 呼び出し] --> B[StatsFactory.create compilation]
    B --> C[module$visible extractor]
    C --> D{profile オプション有効?}
    D -->|Yes| E[moduleGraph.getProfile module]
    E --> F{profile存在?}
    F -->|Yes| G[factory.create profile]
    G --> H[profile extractor で StatsProfile 生成]
    H --> I[module.profile に設定]
    F -->|No| J[profile なしで出力]
    D -->|No| J
    I --> K[JSON シリアライズ]
    J --> K
    K --> L[出力完了]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| プロファイルなし | `moduleGraph.getProfile(module)` が null | エラーは発生せず profile フィールドが省略される | `--profile` オプションを有効にする |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | モジュール数に依存（数百〜数万件） |
| 目標出力時間 | Stats全体の出力に含まれる |
| 同時出力数上限 | N/A |

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

モジュールの識別子にファイルパスが含まれるため、外部公開時はパス情報の漏洩に注意が必要。`requestShortener` によりパスは相対化されるが、プロジェクト構造の推測が可能となる場合がある。

## 備考

- `factory` および `dependencies` プロパティはwebpack 6で削除予定の非推奨フィールドである（lib/stats/DefaultStatsFactoryPlugin.js 1436-1439行目のTODOコメント参照）。
- プロファイル情報の取得には `--profile` フラグが必要であり、ビルド時のオーバーヘッドが発生する。

---

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

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

### 推奨読解順序

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

まず、プロファイルデータの格納構造と出力データ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ModuleProfile.js | `lib/ModuleProfile.js` | プロファイル計測データの格納クラス。各フェーズの開始/終了時刻と所要時間プロパティ（8-44行目） |
| 1-2 | DefaultStatsFactoryPlugin.js | `lib/stats/DefaultStatsFactoryPlugin.js` | KnownStatsProfile 型定義（200-211行目）。出力されるプロファイルデータの構造を定義 |

**読解のコツ**: ModuleProfile は計測用の内部クラス、KnownStatsProfile は外部出力用の型定義。両者のフィールド名が異なる点に注意（例: factory -> resolving）。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Stats.js | `lib/Stats.js` | toJson() メソッド（57-67行目）が Stats 出力のエントリーポイント |

**主要処理フロー**:
1. **57行目**: `toJson(options)` - Stats出力オプションを正規化
2. **62行目**: `createStatsFactory(normalizedOptions)` - StatsFactoryインスタンス生成
3. **64行目**: `statsFactory.create("compilation", ...)` - compilation全体のStats生成開始

#### Step 3: プロファイルデータ計測の仕組み

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ModuleProfile.js | `lib/ModuleProfile.js` | markFactoryStart/End, markBuildingStart/End 等のメソッド（46-89行目）で各フェーズの時間を計測 |

**主要処理フロー**:
- **46-52行目**: `markFactoryStart/End` - モジュール解決時間の計測
- **64-70行目**: `markIntegrationStart/End` - 統合時間の計測
- **72-79行目**: `markBuildingStart/End` - ビルド時間の計測
- **98-105行目**: `mergeInto(realProfile)` - 追加のファクトリ時間をマージ

#### Step 4: プロファイルデータ抽出・変換

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | DefaultStatsFactoryPlugin.js | `lib/stats/DefaultStatsFactoryPlugin.js` | module$visible extractor（1274行目）で moduleGraph.getProfile() を呼びプロファイルデータを取得 |
| 4-2 | DefaultStatsFactoryPlugin.js | `lib/stats/DefaultStatsFactoryPlugin.js` | profile extractor（1419-1442行目）で ModuleProfile を StatsProfile に変換 |

**主要処理フロー**:
- **1274行目**: `moduleGraph.getProfile(module)` でプロファイルデータ取得
- **1310-1316行目**: profile が存在する場合、`factory.create` でサブオブジェクト生成
- **1419-1442行目**: profile extractor で total 計算、フィールド名のマッピング実行

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

```
Stats.toJson()
    │
    ├─ Compilation.createStatsOptions()
    │
    ├─ Compilation.createStatsFactory()
    │
    └─ StatsFactory.create("compilation", compilation)
           │
           ├─ module$visible extractor
           │      ├─ moduleGraph.getProfile(module)
           │      └─ factory.create("module.profile", profile)
           │             │
           │             └─ profile extractor
           │                    └─ StatsProfile オブジェクト生成
           │                       (total, resolving, building 等を算出)
           │
           └─ moduleIssuer extractor
                  └─ factory.create("moduleIssuer.profile", profile)
```

### データフロー図

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

ModuleProfile           DefaultStatsFactoryPlugin        StatsProfile (JSON)
(factory,               profile extractor                (total, resolving,
 restoring,             ──────────────────▶               restoring, building,
 building,              フィールドマッピング +              integration, storing,
 integration,           合計時間計算                       additionalResolving,
 storing,                                                additionalIntegration)
 additionalFactories)
      ▲
      │
moduleGraph.getProfile(module)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ModuleProfile.js | `lib/ModuleProfile.js` | ソース | プロファイル計測データの格納クラス |
| Stats.js | `lib/Stats.js` | ソース | Stats出力のエントリーポイント |
| DefaultStatsFactoryPlugin.js | `lib/stats/DefaultStatsFactoryPlugin.js` | ソース | プロファイルデータの抽出・変換ロジック |
| StatsFactory.js | `lib/stats/StatsFactory.js` | ソース | Stats生成のファクトリクラス |
| Compilation.js | `lib/Compilation.js` | ソース | moduleGraphを保持し、プロファイルデータの登録を管理 |
