# 機能設計書 31-ツリーシェイキング

## 概要

本ドキュメントは、Bunバンドラーにおけるツリーシェイキング（Tree Shaking）機能の設計仕様を記載する。ツリーシェイキングは、未使用コードの自動削除（デッドコード除去）を行い、最終的なバンドル出力のサイズを最適化する機能である。

### 本機能の処理概要

ツリーシェイキングは、JavaScriptおよびTypeScriptのバンドル時に、実際に使用されていないコード（エクスポートされているが参照されていない関数、変数、クラスなど）を自動的に検出し、最終出力から除去する機能である。

**業務上の目的・背景**：モダンなJavaScriptアプリケーションでは、npmパッケージやモジュールシステムを通じて大量のコードがインポートされる。しかし、実際にアプリケーションで使用されるのは、そのうちの一部のみであることが多い。ツリーシェイキングにより、未使用のコードを除去することで、最終的なバンドルサイズを削減し、アプリケーションの読み込み時間を短縮できる。これはWebアプリケーションのパフォーマンス最適化において重要な役割を果たす。

**機能の利用シーン**：本番環境向けのビルド時、ライブラリ開発時のバンドル生成時、パフォーマンス最適化が求められるWebアプリケーション開発時に利用される。`bun build`コマンドでバンドルを生成する際にデフォルトで有効となる。

**主要な処理内容**：
1. ESモジュールの静的解析によるインポート/エクスポート関係の把握
2. 到達可能なコード（Reachable Code）の特定
3. 副作用（Side Effects）の検出と考慮
4. 未使用エクスポートの除去
5. デッドコード部分（Parts）の削除マーキング

**関連システム・外部連携**：バンドラーのパーサー、リンカー、コード生成モジュールと連携して動作する。

**権限による制御**：特になし。CLI/APIオプションでツリーシェイキングの有効/無効を切り替え可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 20 | build | 主画面 | バンドル処理実行時のツリーシェイキング適用 |

## 機能種別

計算処理 / 最適化処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| tree_shaking | bool | No | ツリーシェイキングの有効/無効 | デフォルト: true |
| ignore_dce_annotations | bool | No | DCE(Dead Code Elimination)アノテーションを無視するか | デフォルト: false |
| emit_dce_annotations | bool | No | DCEアノテーションを出力するか | デフォルト: true |

### 入力データソース

- JavaScript/TypeScriptソースファイル
- package.jsonの`sideEffects`フィールド
- CLI/APIオプション

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| バンドルファイル | ファイル | 未使用コードが除去された最適化済みバンドル |
| ソースマップ | ファイル | オプションでソースマップを出力 |

### 出力先

ファイルシステム（指定された出力ディレクトリ）

## 処理フロー

### 処理シーケンス

```
1. パース処理
   └─ 各ソースファイルをAST(抽象構文木)に変換
2. インポート/エクスポート解析
   └─ scanImportsAndExports()でモジュール間の依存関係を解析
3. 到達可能ファイルの特定
   └─ findReachableFiles()でエントリーポイントから到達可能なファイルを特定
4. パート依存関係の解析
   └─ doStep5()で各パート(コード断片)の依存関係を計算
5. 未使用コードのマーキング
   └─ 使用されていないパートを削除対象としてマーク
6. コード生成
   └─ マークされた未使用パートを除外してバンドルを生成
```

### フローチャート

```mermaid
flowchart TD
    A[開始: ソースファイル入力] --> B[パース処理]
    B --> C[インポート/エクスポート解析]
    C --> D[到達可能ファイル特定]
    D --> E{各パートを解析}
    E --> F[シンボル使用状況確認]
    F --> G{使用されているか?}
    G -->|Yes| H[パートを維持]
    G -->|No| I{副作用があるか?}
    I -->|Yes| H
    I -->|No| J[パートを除去マーク]
    H --> K{次のパートあり?}
    J --> K
    K -->|Yes| E
    K -->|No| L[コード生成]
    L --> M[終了: 最適化バンドル出力]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-31-001 | ESモジュール必須 | ツリーシェイキングはESモジュール形式でのみ完全に機能する | ESM形式のソースコード |
| BR-31-002 | 副作用考慮 | sideEffectsがfalseでないモジュールは副作用ありとみなす | package.json設定 |
| BR-31-003 | CommonJS制限 | CommonJSモジュールは静的解析が困難なため、ツリーシェイキングが制限される | require()使用時 |

### 計算ロジック

シンボル使用回数のカウント: 各パートで`symbol_uses`マップを通じてシンボルの使用回数(`count_estimate`)を追跡し、使用回数が0のシンボルを含むパートを除去候補とする。

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

本機能はデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 警告 | 循環参照の検出 | 警告を出力し、安全側に倒して除去しない |
| - | 警告 | 動的インポートの存在 | 動的インポート先は除去しない |

### リトライ仕様

リトライは行わない。

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

該当なし（ファイル処理のみ）

## パフォーマンス要件

- パース処理と並行してツリーシェイキング解析を実行
- スレッドプールを活用した並列処理
- 大規模プロジェクトでも数秒以内で完了すること

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

- ソースコードの内容に基づく処理のため、機密性の高いコードも処理対象となる
- 出力ファイルには最適化後のコードのみが含まれる

## 備考

- `--ignore-dce-annotations`オプションで、`/*#__PURE__*/`などのアノテーションを無視可能
- DevServer使用時はツリーシェイキングが無効化される（開発効率のため）

---

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

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

### 推奨読解順序

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

まず、ツリーシェイキングで使用される主要なデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | LinkerContext.zig | `src/bundler/LinkerContext.zig` | LinkerOptionsのtree_shaking、ignore_dce_annotations、emit_dce_annotationsフィールドを確認 |
| 1-2 | LinkerGraph.zig | `src/bundler/LinkerGraph.zig` | ファイル間の依存関係グラフ構造を理解 |

**読解のコツ**: LinkerContextはバンドラーの中心的なコンテキストオブジェクト。`LinkerOptions`構造体の`tree_shaking: bool = true`がデフォルトで有効になっていることを確認する（59-64行目）。

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

処理の起点となるファイル・関数を特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | bundle_v2.zig | `src/bundler/bundle_v2.zig` | findReachableFiles()が到達可能ファイルを特定する処理 |

**主要処理フロー**:
1. **269-372行目**: ReachableFileVisitorがエントリーポイントから到達可能なファイルを走査
2. **374-462行目**: findReachableFiles()が到達可能ファイルのリストを構築
3. **422-428行目**: code_splittingが有効な場合の動的インポートチェック

#### Step 3: インポート/エクスポート解析を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | scanImportsAndExports.zig | `src/bundler/linker_context/scanImportsAndExports.zig` | モジュール間の依存関係を解析する処理 |

**主要処理フロー**:
- **1-200行目**: scanImportsAndExports()がインポート/エクスポートをスキャン
- **30-167行目**: CommonJSとESMの判定、モジュールのラップ方法を決定

#### Step 4: パート依存関係の解析を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | doStep5.zig | `src/bundler/linker_context/doStep5.zig` | 各パートの依存関係を計算し、使用状況を追跡 |

**主要処理フロー**:
- **1-78行目**: doStep5()が名前空間エクスポートを作成し、エクスポートエイリアスをソート
- **88-200行目**: パートのシンボル使用状況を解析し、依存関係を構築
- **96-137行目**: TypeScript enumのインライン化と使用カウントの更新

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

```
BundleV2.bundle()
    │
    ├─ waitForParse()
    │      └─ 各ファイルのパース完了を待機
    │
    ├─ findReachableFiles()
    │      └─ ReachableFileVisitor.visit()
    │             └─ エントリーポイントから到達可能なファイルを走査
    │
    └─ LinkerContext
           ├─ scanImportsAndExports()
           │      └─ モジュール間のインポート/エクスポート関係を解析
           │
           ├─ doStep5()
           │      ├─ createExportsForFile()
           │      └─ パート依存関係の計算
           │
           └─ generateChunksInParallel()
                  └─ 未使用パートを除外してコード生成
```

### データフロー図

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

ソースファイル ───▶ パース処理 ───▶ AST
                         │
                         ▼
AST ───────────▶ scanImportsAndExports() ───▶ 依存関係グラフ
                         │
                         ▼
依存関係グラフ ──▶ findReachableFiles() ───▶ 到達可能ファイルリスト
                         │
                         ▼
到達可能ファイル ──▶ doStep5() ───▶ パート使用状況
                         │
                         ▼
パート使用状況 ──▶ コード生成 ───▶ 最適化バンドル
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| bundle_v2.zig | `src/bundler/bundle_v2.zig` | ソース | バンドラーのメインエントリーポイント、到達可能ファイル特定 |
| LinkerContext.zig | `src/bundler/LinkerContext.zig` | ソース | リンカーコンテキスト、ツリーシェイキングオプション管理 |
| LinkerGraph.zig | `src/bundler/LinkerGraph.zig` | ソース | ファイル間依存関係グラフ |
| scanImportsAndExports.zig | `src/bundler/linker_context/scanImportsAndExports.zig` | ソース | インポート/エクスポート解析 |
| doStep5.zig | `src/bundler/linker_context/doStep5.zig` | ソース | パート依存関係計算、シンボル使用状況追跡 |
| Chunk.zig | `src/bundler/Chunk.zig` | ソース | チャンク構造、出力ファイル管理 |
| build_command.zig | `src/cli/build_command.zig` | ソース | CLIからのビルドコマンド処理 |
| options.zig | `src/options.zig` | ソース | ビルドオプション定義 |
