# 帳票設計書 8-Stats チャンクレポート

## 概要

本ドキュメントは、webpackビルドで生成されたチャンクの情報を構造化して出力する「Stats チャンクレポート」の設計仕様を定義する。

### 本帳票の処理概要

Stats チャンクレポートは、生成されたチャンク（バンドルファイルの論理単位）のID、名前、サイズ、含有モジュール、初期/非同期区分、ファイル一覧等の情報を出力する帳票である。`SIMPLE_EXTRACTORS.compilation.chunks` および `SIMPLE_EXTRACTORS.chunk` により生成される。

**業務上の目的・背景**：コード分割（Code Splitting）の結果を把握し、チャンク構成の最適化を行うために必要である。初期チャンクとオンデマンドチャンクの区別、チャンク間の親子・兄弟関係、チャンクに含まれるモジュールの確認を可能にする。

**帳票の利用シーン**：コード分割戦略の分析、チャンクサイズの監視、ランタイムチャンクの確認、チャンク間の依存関係分析に利用される。

**主要な出力内容**：
1. チャンク基本情報（id, names, size, sizes, hash）
2. チャンク状態（rendered, initial, entry, recorded）
3. ファイル一覧（files, auxiliaryFiles）
4. チャンク関係（siblings, parents, children, childrenByOrder）
5. ランタイム情報（runtime, idHints）
6. 含有モジュール（modules）
7. チャンク生成理由（reason, origins）

**帳票の出力タイミング**：`Stats.toJson()` または `Stats.toString()` 呼び出し時に生成される。

**帳票の利用者**：フロントエンド開発者、パフォーマンスエンジニア。

## 帳票種別

チャンク一覧出力

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | CLI | `webpack` | ビルド完了時に自動出力 |
| - | Node.js API | プログラム内 | `stats.toJson()` / `stats.toString()` |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | JSON（toJson時）/ テキスト（toString時） |
| 用紙サイズ | N/A |
| 向き | N/A |
| ファイル名 | N/A |
| 出力方法 | StatsCompilation.chunksフィールドとして出力 |
| 文字コード | UTF-8 |

## 帳票レイアウト

### レイアウト概要

StatsChunk型の配列として出力される。

```
{
    "rendered":          レンダリング済みか,
    "initial":           初期チャンクか,
    "entry":             エントリーチャンクか,
    "recorded":          記録済みか,
    "reason":            チャンク生成理由,
    "size":              チャンクサイズ,
    "sizes":             ソースタイプ別サイズ,
    "names":             チャンク名配列,
    "idHints":           IDヒント配列,
    "runtime":           ランタイム配列,
    "files":             出力ファイル配列,
    "auxiliaryFiles":    補助ファイル配列,
    "hash":              レンダリングハッシュ,
    "childrenByOrder":   子チャンクID（順序別）,
    "id":                チャンクID,
    "siblings":          兄弟チャンクID配列,
    "parents":           親チャンクID配列,
    "children":          子チャンクID配列,
    "modules":           含有モジュール配列,
    "filteredModules":   フィルタ済みモジュール数,
    "origins":           チャンク起源情報
}
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | id | チャンクID | chunk.id | 文字列/数値 |
| 2 | names | チャンク名 | chunk.name ? [chunk.name] : [] | 文字列配列 |
| 3 | hash | ハッシュ | chunk.renderedHash | 文字列 |

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | rendered | レンダリング済みか | chunk.rendered | 真偽値 | - |
| 2 | initial | 初期チャンクか | chunk.canBeInitial() | 真偽値 | - |
| 3 | entry | エントリーチャンクか | chunk.hasRuntime() | 真偽値 | - |
| 4 | recorded | 記録済みか | AggressiveSplittingPlugin.wasChunkRecorded(chunk) | 真偽値 | - |
| 5 | reason | 生成理由 | chunk.chunkReason | 文字列 | - |
| 6 | size | チャンクサイズ | chunkGraph.getChunkModulesSize(chunk) | 数値（バイト） | - |
| 7 | sizes | ソースタイプ別サイズ | chunkGraph.getChunkModulesSizes(chunk) | Record<string, number> | - |
| 8 | files | 出力ファイル | [...chunk.files] | 文字列配列 | - |
| 9 | auxiliaryFiles | 補助ファイル | [...chunk.auxiliaryFiles].sort() | 文字列配列 | - |
| 10 | runtime | ランタイム | chunk.runtime | 文字列配列 | - |
| 11 | idHints | IDヒント | [...chunk.idNameHints] | 文字列配列 | - |
| 12 | childrenByOrder | 子チャンク（順序別） | chunk.getChildIdsByOrders(chunkGraph) | Record<string, ChunkId[]> | - |

### フッター部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | siblings | 兄弟チャンクID | chunkGroup.chunks | ChunkId[] |
| 2 | parents | 親チャンクID | chunkGroup.parentsIterable | ChunkId[] |
| 3 | children | 子チャンクID | chunkGroup.childrenIterable | ChunkId[] |
| 4 | modules | 含有モジュール | chunkGraph.getChunkModules(chunk) | StatsModule[] |
| 5 | origins | チャンク起源 | chunkGroup.origins | StatsChunkOrigin[] |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| ids | ID情報（id, siblings, parents, children）の出力 | No |
| chunkRelations | チャンク関係（siblings, parents, children）の出力 | No |
| chunkModules | 含有モジュールの出力 | No |
| chunkModulesSpace | 含有モジュール表示のスペース制限 | No |
| chunkOrigins | チャンク起源の出力 | No |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | id | 昇順 |

### 改ページ条件

N/A

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

### 参照テーブル一覧

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| Compilation | チャンク一覧 | compilation.chunks |
| ChunkGraph | チャンクサイズ・モジュール | chunkGraph |
| ChunkGroup | チャンク関係 | chunk.groupsIterable |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| size | chunkGraph.getChunkModulesSize(chunk) | なし | バイト単位 |
| sizes | chunkGraph.getChunkModulesSizes(chunk) | なし | ソースタイプ別 |
| initial | chunk.canBeInitial() | - | 真偽値 |
| entry | chunk.hasRuntime() | - | 真偽値 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[SIMPLE_EXTRACTORS.compilation.chunks] --> B[compilation.chunksをArray化]
    B --> C[factory.create compilation.chunks 呼び出し]
    C --> D[SORTERS compilation.chunks でID順ソート]
    D --> E[chunk._ で基本情報抽出]
    E --> F[chunk.ids でID情報抽出]
    F --> G[chunk.chunkRelations で関係情報抽出]
    G --> H[chunk.chunkModules で含有モジュール抽出]
    H --> I[chunk.chunkOrigins で起源情報抽出]
    I --> J[StatsChunk配列返却]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| チャンクなし | compilation.chunksが空 | 空配列返却 | ビルド設定を確認 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | チャンク数十〜数百 |
| 目標出力時間 | チャンク数に比例 |
| 同時出力数上限 | 1 |

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

チャンク情報にはファイル名が含まれるが、通常は相対パスであるためリスクは低い。ただし、含有モジュール情報にはファイルパスが含まれる。

## 備考

- `recorded` はAggressiveSplittingPlugin使用時にチャンクが記録されたかを示す
- `runtime` はチャンクのランタイム文字列で、makePathsRelativeで相対化される
- `childrenByOrder` はチャンクグループの子順序（prefetch / preload等）を示す
- チャンク起源（origins）は重複除去された後に出力される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | DefaultStatsFactoryPlugin.js | `lib/stats/DefaultStatsFactoryPlugin.js` | 行239-263: `KnownStatsChunk` 型定義 |
| 1-2 | DefaultStatsFactoryPlugin.js | `lib/stats/DefaultStatsFactoryPlugin.js` | 行265-274: `KnownStatsChunkOrigin` 型定義 |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | DefaultStatsFactoryPlugin.js | `lib/stats/DefaultStatsFactoryPlugin.js` | 行844-851: `SIMPLE_EXTRACTORS.compilation.chunks` |

#### Step 3: chunk抽出処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | DefaultStatsFactoryPlugin.js | `lib/stats/DefaultStatsFactoryPlugin.js` | 行1508-1535: `SIMPLE_EXTRACTORS.chunk._` - rendered, initial, entry, recorded, reason, size, sizes, names, idHints, runtime, files, auxiliaryFiles, hash, childrenByOrder |
| 3-2 | DefaultStatsFactoryPlugin.js | `lib/stats/DefaultStatsFactoryPlugin.js` | 行1536-1538: `chunk.ids` - chunk.id |
| 3-3 | DefaultStatsFactoryPlugin.js | `lib/stats/DefaultStatsFactoryPlugin.js` | 行1539-1568: `chunk.chunkRelations` - siblings, parents, children |
| 3-4 | DefaultStatsFactoryPlugin.js | `lib/stats/DefaultStatsFactoryPlugin.js` | 行1569-1583: `chunk.chunkModules` - chunkGraph.getChunkModules → spaceLimited |
| 3-5 | DefaultStatsFactoryPlugin.js | `lib/stats/DefaultStatsFactoryPlugin.js` | 行1584-1607: `chunk.chunkOrigins` - 重複除去 → factory.create |

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

```
SIMPLE_EXTRACTORS.compilation.chunks()
    |
    +-- [...compilation.chunks] Array化
    +-- factory.create("compilation.chunks", [...chunks], context)
            |
            +-- SORTERS["compilation.chunks"] (id昇順)
            +-- chunk._()
            |       +-- rendered, initial, entry, recorded
            |       +-- reason, size, sizes
            |       +-- names, idHints, runtime
            |       +-- files, auxiliaryFiles, hash
            |       +-- childrenByOrder
            |
            +-- chunk.ids() → id
            |
            +-- chunk.chunkRelations()
            |       +-- chunkGroup.parentsIterable → parents
            |       +-- chunkGroup.childrenIterable → children
            |       +-- chunkGroup.chunks → siblings
            |
            +-- chunk.chunkModules()
            |       +-- chunkGraph.getChunkModules(chunk)
            |       +-- factory.create("chunk.modules", ...)
            |       +-- spaceLimited()
            |
            +-- chunk.chunkOrigins()
                    +-- chunkGroup.origins 重複除去
                    +-- factory.create("chunk.origins", ...)
                            +-- chunkOrigin._()
                            +-- chunkOrigin.ids()
```

### データフロー図

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

compilation.chunks          -->  chunk._()                      -->  StatsChunk[]
  Chunk[]                   -->    rendered/initial/entry判定    -->    .rendered, .initial, .entry
chunkGraph                  -->    size/sizes計算               -->    .size, .sizes
  .getChunkModulesSize()    -->    files/auxiliaryFiles取得     -->    .files, .auxiliaryFiles
chunk.groupsIterable        -->  chunk.chunkRelations()         -->    .siblings, .parents, .children
chunkGroup.origins          -->  chunk.chunkOrigins()           -->    .origins
chunkGraph.getChunkModules  -->  chunk.chunkModules()           -->    .modules
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| DefaultStatsFactoryPlugin.js | `lib/stats/DefaultStatsFactoryPlugin.js` | ソース | chunk / chunkOrigin 抽出処理 |
| StatsFactory.js | `lib/stats/StatsFactory.js` | ソース | データ変換パイプライン |
| Stats.js | `lib/Stats.js` | ソース | toJson() / toString() エントリーポイント |
| Compilation.js | `lib/Compilation.js` | ソース | chunks提供 |
| ChunkGraph.js | `lib/ChunkGraph.js` | ソース | チャンクサイズ・モジュール関係 |
| AggressiveSplittingPlugin.js | `lib/optimize/AggressiveSplittingPlugin.js` | ソース | wasChunkRecorded判定 |
