# 帳票設計書 6-Stats アセットレポート

## 概要

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

### 本帳票の処理概要

Stats アセットレポートは、ビルドで生成されたアセット（JSファイル、CSSファイル、画像等）のファイル名、サイズ、関連チャンク情報、emitted/cached状態等の一覧を出力する帳票である。`SIMPLE_EXTRACTORS.compilation.assets` および `SIMPLE_EXTRACTORS.asset` / `asset$visible` により生成される。

**業務上の目的・背景**：ビルド成果物の一覧と各ファイルのサイズを把握し、バンドルサイズの最適化やキャッシュ戦略の検討を行うために必要である。特にサイズ上限超過（isOverSizeLimit）の検出は、パフォーマンス最適化の重要な指標となる。

**帳票の利用シーン**：ビルド成果物の確認、バンドルサイズ監視、CDNデプロイ時のファイル一覧確認、パフォーマンス警告の根拠データとして利用される。

**主要な出力内容**：
1. アセットタイプ（type: "asset" / ソースマップ等）
2. ファイル名（name）
3. ファイルサイズ（size）
4. emitted/comparedForEmit/cached状態
5. アセット情報（info: immutable, sourceFilename, development, hmr等）
6. 関連チャンク名・ID
7. 関連アセット（related）
8. サイズ上限超過フラグ（isOverSizeLimit）

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

**帳票の利用者**：フロントエンド開発者、DevOpsエンジニア、バンドル分析ツール。

## 帳票種別

アセット一覧出力

## 利用画面

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

## 出力形式

### 基本仕様

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

## 帳票レイアウト

### レイアウト概要

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

```
{
    "type":               アセットタイプ（"asset"が基本）,
    "name":               ファイル名,
    "size":               ファイルサイズ（バイト）,
    "emitted":            出力済みフラグ,
    "comparedForEmit":    出力比較済みフラグ,
    "cached":             キャッシュフラグ,
    "info": {
        "immutable":       イミュータブルフラグ,
        "sourceFilename":  元ファイル名,
        "development":     開発用フラグ,
        "hotModuleReplacement": HMR用フラグ,
        "javascriptModule": JSモジュールフラグ
    },
    "chunkNames":         関連チャンク名配列,
    "chunkIdHints":       チャンクIDヒント配列,
    "chunks":             関連チャンクID配列,
    "auxiliaryChunkNames": 補助チャンク名配列,
    "auxiliaryChunks":    補助チャンクID配列,
    "related":            関連アセット配列,
    "filteredRelated":    フィルタされた関連アセット数,
    "isOverSizeLimit":    サイズ上限超過フラグ
}
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | type | アセットタイプ | asset.type / related.type | 文字列 |
| 2 | name | ファイル名 | asset.name | 文字列 |
| 3 | size | ファイルサイズ | asset.source.size() | 数値（バイト） |

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | emitted | 出力済みか | compilation.emittedAssets.has(name) | 真偽値 | - |
| 2 | comparedForEmit | 出力比較済みか | compilation.comparedForEmitAssets.has(name) | 真偽値 | - |
| 3 | cached | キャッシュか | !emitted && !comparedForEmit | 真偽値 | - |
| 4 | info | アセット情報 | asset.info | オブジェクト | - |
| 5 | chunkNames | 関連チャンク名 | compilationFileToChunks → chunk.name | 文字列配列 | - |
| 6 | chunkIdHints | チャンクIDヒント | compilationFileToChunks → chunk.idNameHints | 文字列配列 | - |
| 7 | chunks | 関連チャンクID | compilationFileToChunks → chunk.ids | ID配列 | - |
| 8 | auxiliaryChunkNames | 補助チャンク名 | compilationAuxiliaryFileToChunks | 文字列配列 | - |
| 9 | auxiliaryChunks | 補助チャンクID | compilationAuxiliaryFileToChunks | ID配列 | - |
| 10 | related | 関連アセット | asset.info.related | StatsAsset[] | - |
| 11 | isOverSizeLimit | サイズ上限超過 | SizeLimitsPlugin.isOverSizeLimit() | 真偽値 | - |

### フッター部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | filteredAssets | フィルタされたアセット数 | spaceLimited() | 数値 |
| 2 | filteredRelated | フィルタされた関連アセット数 | related.length - object.related.length | 数値 |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| cachedAssets | キャッシュ済みアセットの表示有効/無効 | No |
| assetsSpace | アセット表示のスペース制限 | No |
| relatedAssets | 関連アセットの表示有効/無効 | No |
| performance | サイズ上限超過判定の有効/無効 | No |

### ソート順

アセットはcompilation.getAssets()の返却順序で処理される。関連アセットはasset.info.relatedから取得される。

### 改ページ条件

N/A

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

### 参照テーブル一覧

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| Compilation | アセット一覧取得 | compilation.getAssets() |
| Compilation | emittedAssets確認 | compilation.emittedAssets |
| Compilation | comparedForEmitAssets確認 | compilation.comparedForEmitAssets |
| Chunk | チャンク-ファイル対応 | chunk.files / chunk.auxiliaryFiles |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| size | asset.source.size() | なし | バイト単位 |
| cached | !emitted && !comparedForEmit | - | 論理演算 |
| assetsByChunkName | chunk.files/auxiliaryFiles → chunk.name のマッピング | - | Record<string, string[]> |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[SIMPLE_EXTRACTORS.compilation.assets] --> B[compilationFileToChunks Map構築]
    B --> C[compilationAuxiliaryFileToChunks Map構築]
    C --> D[compilation.getAssets でアセット一覧取得]
    D --> E[related情報で親子関係構築]
    E --> F[assetsByChunkName構築]
    F --> G[factory.create compilation.assets 呼び出し]
    G --> H[SIMPLE_EXTRACTORS.asset._ で基本情報抽出]
    H --> I{cached && !cachedAssets?}
    I -->|Yes| J[visible情報スキップ]
    I -->|No| K[asset$visible で詳細情報抽出]
    K --> L[spaceLimited でスペース制限]
    L --> M[StatsAsset配列返却]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| アセットなし | compilation.getAssets()が空 | 空配列返却 | ビルド設定を確認 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | アセット数十〜数百 |
| 目標出力時間 | アセット数に比例（通常ミリ秒単位） |
| 同時出力数上限 | 1 |

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

アセットファイル名にはビルド出力パス情報が含まれる。sourceFilename情報にはソースファイルの元パスが含まれる可能性がある。

## 備考

- アセットのtype分類: "asset"（通常アセット）、ソースマップやライセンスファイル等のrelated assetは別typeが設定される
- related assetはメインアセットから分離され、メインアセットのrelated配列に格納される
- `cachedAssets: false` の場合、キャッシュされたアセットの詳細情報（chunkNames等）は出力されない
- `spaceLimited` によりassetsSpace上限でアセット数が制限される

---

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

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

### 推奨読解順序

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

StatsAsset型の定義を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | DefaultStatsFactoryPlugin.js | `lib/stats/DefaultStatsFactoryPlugin.js` | 行115-135: `KnownStatsAsset` 型定義。type, name, size, emitted, comparedForEmit, cached, info, chunks, chunkNames, related, isOverSizeLimit 等 |

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

compilation.assets 抽出処理を読む。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | DefaultStatsFactoryPlugin.js | `lib/stats/DefaultStatsFactoryPlugin.js` | 行754-843: `SIMPLE_EXTRACTORS.compilation.assets` - FileToChunksマップ構築、アセット前処理、related分離、assetsByChunkName構築、spaceLimited |

**主要処理フロー**:
1. **行757-777**: `compilationFileToChunks` / `compilationAuxiliaryFileToChunks` マップ構築
2. **行779-810**: アセット前処理（PreprocessedAsset化、related分離）
3. **行812-830**: `assetsByChunkName` 構築
4. **行832-836**: `factory.create("compilation.assets", ...)` で構造化
5. **行837-842**: `spaceLimited(groupedAssets, assetsSpace)` でスペース制限

#### Step 3: asset / asset$visible 抽出処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | DefaultStatsFactoryPlugin.js | `lib/stats/DefaultStatsFactoryPlugin.js` | 行1027-1047: `SIMPLE_EXTRACTORS.asset._` - type, name, size, emitted, comparedForEmit, cached, info |
| 3-2 | DefaultStatsFactoryPlugin.js | `lib/stats/DefaultStatsFactoryPlugin.js` | 行1048-1113: `SIMPLE_EXTRACTORS.asset$visible` - chunkNames, chunkIdHints, chunks, auxiliaryChunks, related, isOverSizeLimit |

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

```
SIMPLE_EXTRACTORS.compilation.assets()
    |
    +-- compilationFileToChunks Map構築
    +-- compilationAuxiliaryFileToChunks Map構築
    +-- compilation.getAssets() → PreprocessedAsset前処理
    +-- related情報による親子関係構築
    +-- assetsByChunkName構築
    |
    +-- factory.create("compilation.assets", [...assets], context)
    |       |
    |       +-- asset._()
    |       |       +-- type, name, size設定
    |       |       +-- emitted / comparedForEmit / cached判定
    |       |       +-- info設定
    |       |       +-- asset$visible()（cachedでない場合）
    |       |               +-- chunkNames / chunkIdHints
    |       |               +-- auxiliaryChunkNames / auxiliaryChunkIdHints
    |       |               +-- chunks / auxiliaryChunks（ids有効時）
    |       |               +-- related（relatedAssets有効時）
    |       |               +-- isOverSizeLimit（performance有効時）
    |       |
    +-- spaceLimited(groupedAssets, assetsSpace)
```

### データフロー図

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

compilation.getAssets()     -->  PreprocessedAsset前処理         -->  StatsAsset[]
  Asset[]                   -->  asset._()                      -->    .type, .name, .size
compilation.emittedAssets   -->  emitted判定                    -->    .emitted
compilation.comparedFor...  -->  comparedForEmit判定            -->    .comparedForEmit
chunk.files                -->  compilationFileToChunks         -->    .chunkNames, .chunks
chunk.auxiliaryFiles       -->  compilationAuxiliaryFileToChunks -->   .auxiliaryChunkNames
asset.info.related         -->  related分離処理                 -->    .related
SizeLimitsPlugin           -->  isOverSizeLimit判定             -->    .isOverSizeLimit
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| DefaultStatsFactoryPlugin.js | `lib/stats/DefaultStatsFactoryPlugin.js` | ソース | compilation.assets / asset / asset$visible 抽出処理 |
| StatsFactory.js | `lib/stats/StatsFactory.js` | ソース | データ変換パイプライン |
| Stats.js | `lib/Stats.js` | ソース | toJson() / toString() エントリーポイント |
| DefaultStatsPrinterPlugin.js | `lib/stats/DefaultStatsPrinterPlugin.js` | ソース | ASSET_SIMPLE_PRINTERSでテキスト表示 |
| Compilation.js | `lib/Compilation.js` | ソース | getAssets() / emittedAssets / comparedForEmitAssets 提供 |
| SizeLimitsPlugin.js | `lib/performance/SizeLimitsPlugin.js` | ソース | isOverSizeLimit判定 |
