# バッチ設計書 3-tooling/generate-runtime-code.js

## 概要

本ドキュメントは、ランタイムコードの自動生成スクリプト `tooling/generate-runtime-code.js` の設計仕様を定義するものである。lib/util/semver.js内のランタイムコード領域をterserで圧縮・最小化し、テンプレートリテラル形式で再生成する。

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

`tooling/generate-runtime-code.js` は、webpackのランタイムコードを自動生成するためのスクリプトである。`lib/util/semver.js` に定義されたアロー関数形式のランタイムコードを読み取り、terserで圧縮（minify）した上で、webpack内部のruntimeTemplate形式のテンプレートリテラルとして再生成する。生成結果はprettierでフォーマットされた後、元のファイルに書き戻される。

**業務上の目的・背景**：webpackのランタイムコードはブラウザ環境で実行されるため、バンドルサイズの最小化が重要である。開発時は可読性の高いアロー関数形式で記述し、ビルド時にterserで圧縮された最小化コードを自動生成することで、可読性と最適化の両立を実現する。また、runtimeTemplateを介してアロー関数のサポート状況に応じたコード出力を可能にしている。

**バッチの実行タイミング**：`lint:special` / `fix:special` のnpmスクリプトから実行される。CIパイプラインでのリントチェック時（変更検出モード）および開発時の修正モード（--writeオプション）で使用される。

**主要な処理内容**：
1. `lib/util/semver.js` ファイルを読み込む
2. `//#region runtime code: {name}` 〜 `//#endregion` で囲まれたランタイムコード領域を正規表現で検出する
3. 対応するexport関数を取得し、アロー関数のヘッダー（引数部分）と本体を分離する
4. terserで本体部分をminify（圧縮）する（ecma: 5、toplevel: true、compress: true、mangle: true）
5. minifyされたコードをruntimeTemplate.basicFunction形式のテンプレートリテラルに変換する
6. prettierでフォーマット後、変更がある場合は --write オプションに応じてファイル書き込みまたは差分検出（exitCode=1）を行う

**前後の処理との関連**：`lint:special` スクリプトの一部として実行される。`--write` なしで実行された場合はコードが最新かどうかのチェックのみを行い、差分があればexitCode=1で終了する。`fix:special` では `--write` 付きで実行され、実際のファイル更新を行う。

**影響範囲**：`lib/util/semver.js` ファイルのランタイムコード領域。生成されたコードはwebpackのバンドル出力に含まれるため、最終的なバンドル品質に直接影響する。

## バッチ種別

コード生成 / ビルドツール

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 随時（lint:special / fix:special の一部として実行） |
| 実行時刻 | 任意 |
| 実行曜日 | N/A |
| 実行日 | N/A |
| トリガー | 手動（npm run lint:special / npm run fix:special）またはCI/CD |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| Node.js 16以上 | Node.js 16以上が必要（コード内で明示的にチェック） |
| terserパッケージ | devDependencyとしてインストール済みであること |
| prettierパッケージ | devDependencyとしてインストール済みであること |
| lib/util/semver.js | ランタイムコード領域を含むソースファイルが存在すること |

### 実行可否判定

Node.jsのメジャーバージョンが16未満の場合、エラーをスローして即座に終了する。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| --write | フラグ | No | false | ファイルへの書き込みを有効にする。指定しない場合はチェックモード |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| lib/util/semver.js | JavaScriptファイル | ランタイムコード領域を含むソースファイル |
| prettierの設定ファイル | 設定ファイル | prettierのフォーマット設定（prettier.resolveConfigで解決） |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| lib/util/semver.js | JavaScriptファイル | --writeオプション指定時にランタイムコード領域を更新 |
| 標準エラー出力（stderr） | テキスト | ファイル更新メッセージまたは更新必要メッセージ |
| process.exitCode | 数値 | 0: 変更なしまたは書き込み成功、1: チェックモードで差分検出 |

### 出力ファイル仕様

| 項目 | 内容 |
|-----|------|
| ファイル名 | lib/util/semver.js（既存ファイルの上書き更新） |
| 出力先 | プロジェクトルート相対 |
| 文字コード | UTF-8 |
| 区切り文字 | N/A |

## 処理フロー

### 処理シーケンス

```
1. Node.jsバージョンチェック（16以上必須）
   └─ process.versions.nodeのメジャーバージョンを確認
2. 対象ファイル（lib/util/semver.js）の読み込み
   └─ fs.readFileSync でUTF-8テキストとして読み込み
3. ランタイムコード領域の検出
   └─ 正規表現 /\n\/\/#region runtime code: (.+)\n[\s\S]+?\/\/#endregion\n/g でマッチ
4. 各ランタイムコード領域の処理
   └─ 対応するexport関数をrequireで取得
   └─ アロー関数ヘッダーの解析（引数と本体の分離）
   └─ アロー関数のブロック本体形式であることを検証
   └─ terserでminify（ecma: 5, toplevel: true, compress: true, mangle: true, bare_returns: true）
   └─ minify結果にES6+構文（テンプレートリテラル、const、let、アロー関数、スプレッド）がないか検証
   └─ runtimeTemplate.basicFunction形式のテンプレートリテラルに変換
   └─ function式をruntimeTemplate.supportsArrowFunction()による条件分岐に置換
5. prettierでフォーマット
   └─ prettier.resolveConfig でファイルパスに基づく設定を解決
   └─ prettier.format で整形
6. 差分判定・出力
   └─ 内容に変更がある場合：--write時はファイル書き込み、それ以外はexitCode=1
   └─ 内容に変更がない場合：何もしない
```

### フローチャート

```mermaid
flowchart TD
    A[バッチ開始] --> B{Node.js >= 16?}
    B -->|No| C[エラースロー]
    B -->|Yes| D[lib/util/semver.js読み込み]
    D --> E[正規表現でランタイムコード領域検出]
    E --> F{領域あり?}
    F -->|No| G[処理終了]
    F -->|Yes| H[export関数取得・アロー関数解析]
    H --> I{アロー関数ブロック本体形式?}
    I -->|No| C
    I -->|Yes| J[terserでminify]
    J --> K{minify結果にES6+構文含む?}
    K -->|Yes| C
    K -->|No| L[runtimeTemplate形式に変換]
    L --> M[prettierでフォーマット]
    M --> N{内容に変更あり?}
    N -->|No| G
    N -->|Yes| O{--writeオプション?}
    O -->|Yes| P[ファイル書き込み]
    O -->|No| Q[exitCode=1で終了]
    P --> G
    Q --> G
```

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

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

本バッチはデータベースを操作しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| Error | Node.jsバージョン不足 | Node.js 16未満で実行 | Node.js 16以上にアップデート |
| Error | アロー関数形式不正 | ランタイムexportがブロック本体のアロー関数でない | ソースコードをアロー関数のブロック本体形式に修正 |
| Error | コードスタイル違反 | minify結果にES6+構文が含まれる | ソースコードをES5互換の構文に修正 |
| Error | minify失敗 | terserがコード生成に失敗 | ソースコードの構文を確認して修正 |
| exitCode=1 | 差分検出 | チェックモードで更新が必要な場合 | --writeオプション付きで再実行 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A（リトライ機構は未実装） |

### 障害時対応

エラー発生時はエラーメッセージに従ってソースコードを修正する。特にランタイムコードのエクスポートがアロー関数のブロック本体形式（`(args) => { ... }`）であることを確認する。

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | N/A（データベース操作なし） |
| コミットタイミング | N/A |
| ロールバック条件 | N/A |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | 1ファイル（lib/util/semver.js）内の複数ランタイムコード領域 |
| 目標処理時間 | 数秒以内 |
| メモリ使用量上限 | 特に制限なし（Node.jsデフォルト） |

## 排他制御

排他制御は行わない。同一ファイルに対する同時書き込みが発生した場合、最後の書き込みが有効になる。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| 更新ログ | --writeモードでファイル更新時 | "{file} updated"（stderrに出力） |
| 差分検出ログ | チェックモードで差分検出時 | "{file} need to be updated"（stderrに出力） |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| N/A | N/A | N/A（監視設定は未実装） |

## 備考

- ランタイムコードは `(args) => { ... }` 形式のアロー関数として記述する必要がある。function宣言や式本体のアロー関数は非対応
- terserのminify設定でecma: 5を指定しているため、ES5互換の出力のみが許可される
- minify結果にテンプレートリテラル（バッククォート）、const、let、アロー関数（=>）、スプレッド演算子（...）が含まれる場合はエラーとなる
- runtimeTemplate.supportsArrowFunction()によるポリフィル対応が組み込まれており、function式をアロー関数に条件分岐で置換する
- `lint:special` スクリプトでは `--write` なしで実行され、差分がある場合にCI/CDが失敗する
- `fix:special` スクリプトでは `--write` 付きで実行され、ファイルが自動更新される
