# バッチ設計書 46-asset-map:compile

## 概要

本ドキュメントは、Symfony AssetMapperコンポーネントの `asset-map:compile` コマンドのバッチ設計書である。マップされた全アセットをコンパイルし、最終出力ディレクトリ（通常 `public/assets`）に書き込むデプロイ用コンソールコマンドについて、処理フロー、入出力仕様、エラー処理等を定義する。

### 本バッチの処理概要

`asset-map:compile` コマンドは、AssetMapperに登録された全アセット（JavaScript、CSS、画像等）をコンパイルし、マニフェストファイルとインポートマップデータを生成してパブリックディレクトリに書き出すデプロイメントコマンドである。

**業務上の目的・背景**：Symfony AssetMapperは、Webpackなどのバンドラーを使用せずにフロントエンドアセットを管理するための仕組みである。開発環境ではアセットを動的に提供するが、本番環境ではパフォーマンスのため事前コンパイルが必要となる。本コマンドは、デプロイプロセスにおいてアセットを最終的なパブリックディレクトリにコピー・コンパイルし、マニフェストファイルやインポートマップキャッシュを生成するために使用される。

**バッチの実行タイミング**：デプロイ時。本番環境へのデプロイプロセスの一環として実行される。

**主要な処理内容**：
1. PreAssetsCompileEventの発行（拡張ポイント）
2. 既存のコンパイル済みコンフィグファイルの削除
3. 全アセットのコンパイルとパブリックディレクトリへの書き込み
4. マニフェストファイルの生成・保存
5. インポートマップデータの生成・保存
6. エントリポイントメタデータの生成・保存

**前後の処理との関連**：`cache:clear` や `cache:warmup` と並んでデプロイスクリプトに組み込まれることが多い。`importmap:install` でダウンロードしたアセットを本番用にコンパイルする。

**影響範囲**：パブリックディレクトリ配下のアセットファイル、マニフェストファイル、インポートマップキャッシュファイルに影響する。既存のコンパイル済みファイルは上書きされる。

## バッチ種別

アセットコンパイル / デプロイメント

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | デプロイ時 |
| 実行時刻 | デプロイプロセスに依存 |
| 実行曜日 | 該当なし |
| 実行日 | 該当なし |
| トリガー | デプロイスクリプト / 手動 |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| AssetMapperの設定 | Symfony AssetMapperが設定されていること |
| アセットの存在 | マップ対象のアセットファイルが存在すること |
| 書き込み権限 | パブリック出力ディレクトリに書き込み権限があること |

### 実行可否判定

特別な実行可否判定ロジックはない。前提条件が満たされていれば実行可能。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| なし | - | - | - | 入力パラメータなし |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| AssetMapperに登録されたアセット | ファイルシステム | マップ済みの全アセットファイル |
| ImportMapGenerator | PHP設定 | インポートマップの設定情報 |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| パブリックアセットディレクトリ | 各種ファイル | コンパイル済みアセットファイル |
| マニフェストファイル | JSON | アセットの論理パスとパブリックパスのマッピング |
| インポートマップキャッシュ | JSON | インポートマップデータ |
| エントリポイントキャッシュ | JSON | エントリポイントごとのeager importデータ |
| コンソール（stdout） | テキスト | コンパイル結果メッセージ |

### 出力ファイル仕様

| 項目 | 内容 |
|-----|------|
| マニフェストファイル | manifest.json（AssetMapper::MANIFEST_FILE_NAME） |
| インポートマップキャッシュ | ImportMapGenerator::IMPORT_MAP_CACHE_FILENAME |
| エントリポイントキャッシュ | ImportMapGenerator::ENTRYPOINT_CACHE_FILENAME_PATTERN（エントリポイントごと） |
| 出力先 | PublicAssetsFilesystemInterfaceのdestinationPath |

## 処理フロー

### 処理シーケンス

```
1. PreAssetsCompileEventの発行
   └─ EventDispatcherを通じてイベントを発行（リスナーによる前処理が可能）
2. 既存コンフィグの削除
   ├─ マニフェストファイルの削除
   ├─ インポートマップキャッシュの削除
   └─ 各エントリポイントキャッシュの削除
3. アセットのコンパイルと書き込み
   ├─ 全アセットのイテレーション
   ├─ コンテンツが変更されたアセットはwrite（コンパイル済みコンテンツを書き込み）
   ├─ コンテンツ未変更のアセットはcopy（ソースからそのままコピー）
   └─ マニフェストの構築（logicalPath → publicPath）
4. マニフェストの保存
   └─ ソート済みマニフェストをJSONファイルとして保存
5. インポートマップデータの保存
   └─ getRawImportMapData()の結果を保存
6. エントリポイントメタデータの保存
   └─ 各エントリポイントのeager importデータを保存
7. デバッグモード警告（該当する場合）
   └─ isDebug=trueの場合、アセット変更が反映されない旨の警告を表示
```

### フローチャート

```mermaid
flowchart TD
    A[バッチ開始] --> B[PreAssetsCompileEvent発行]
    B --> C[既存コンフィグ削除]
    C --> D[全アセットのイテレーション]
    D --> E{コンテンツ変更あり?}
    E -->|Yes| F[write: コンパイル済みコンテンツ書き込み]
    E -->|No| G[copy: ソースからコピー]
    F --> H[マニフェストエントリ追加]
    G --> H
    H --> I{次アセットあり?}
    I -->|Yes| D
    I -->|No| J[マニフェスト保存]
    J --> K[インポートマップデータ保存]
    K --> L[エントリポイントメタデータ保存]
    L --> M{デバッグモード?}
    M -->|Yes| N[警告表示]
    M -->|No| O[バッチ終了]
    N --> O
```

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

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

データベース操作なし。ファイルシステムへの書き込みのみ。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ファイルシステムエラー | 出力先ディレクトリに書き込み権限なし | ディレクトリのパーミッションを確認 |
| - | ファイルシステムエラー | ソースアセットファイルが読み取り不可 | ファイルの存在とパーミッションを確認 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし（単発実行） |
| リトライ間隔 | 該当なし |
| リトライ対象エラー | 該当なし |

### 障害時対応

コンパイル途中で失敗した場合、出力ディレクトリには一部のアセットのみが書き込まれた不完全な状態になる。出力ディレクトリをクリアして再実行することが推奨される。

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | なし（ファイル単位で書き込み） |
| コミットタイミング | 各ファイル書き込み完了時 |
| ロールバック条件 | なし（手動でのクリアが必要） |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | マップ済みアセット数に依存（数十〜数千件） |
| 目標処理時間 | アセット数とサイズに依存 |
| メモリ使用量上限 | コンパイル済みコンテンツをメモリに保持するアセットがある場合は注意 |

## 排他制御

コマンドレベルでの排他制御は行われていない。デプロイプロセス中に一度だけ実行されることが前提。同時実行は出力ファイルの競合を招くため避けること。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| コンパイル開始 | アセット処理開始時 | "Compiling and writing asset files to {path}" |
| コンパイル完了 | アセット処理完了時 | "Compiled {count} assets" |
| マニフェスト | マニフェスト保存時 | "Manifest written to {path}" |
| インポートマップ | インポートマップ保存時 | "Import map data written to {path}" |
| エントリポイント | エントリポイント保存時 | "Entrypoint metadata written for {count} entrypoints ({names})" |
| 警告 | デバッグモード時 | "Debug mode is enabled..." |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| リターンコード | 0以外の場合 | デプロイパイプラインの失敗通知 |

## 備考

- デプロイ時の使用を想定したコマンドであり、開発環境での実行は通常不要
- デバッグモード（isDebug=true）でコンパイルした場合、アセットの変更がコンパイル済みファイルの削除まで反映されない旨の警告が表示される
- PreAssetsCompileEventを通じて、コンパイル前の前処理をカスタマイズ可能
- マニフェストのキーはksort()でソートされる
- asset.contentがnullでない場合はAssetMapperCompilerによってコンテンツが変更されたとみなし、write()で書き込む。nullの場合はcopy()でソースファイルをそのままコピーする
- リターンコードは常に0（成功）を返す
