# 機能設計書 69-Hot Module Replacement

## 概要

本ドキュメントは、Next.jsのHot Module Replacement（HMR）機能の設計について記述する。HMRは開発時にモジュールの変更を検知し、ブラウザのフルリロードなしにモジュールを差し替える機能であり、Webpack HMR・Turbopack HMR・Rspack HMRの3つのバンドラー実装をサポートする。

### 本機能の処理概要

HMRは、ファイル変更時にブラウザ全体をリロードすることなく、変更されたモジュールのみを動的に差し替える仕組みである。これにより、アプリケーションの状態（フォーム入力、スクロール位置等）を保持したまま、コード変更を即座に反映できる。

**業務上の目的・背景**：開発中のフルページリロードは、アプリケーション状態の喪失と待ち時間を引き起こす。HMRにより、状態を保持したまま変更を即座に反映することで、開発者の生産性を大幅に向上させる。

**機能の利用シーン**：`next dev`コマンドでの開発中に、ソースファイル（TSX/JSX/CSS等）を保存するたびに自動的に動作する。

**主要な処理内容**：
1. WebSocket接続の確立（サーバー↔ブラウザ間）
2. ファイル変更の検知とコンパイル実行
3. HMRメッセージの送信（building、sync、built等）
4. クライアント側でのモジュール差し替え（React Fast Refresh統合）
5. Server Componentsの変更処理（serverComponentChanges）
6. ミドルウェアの変更処理（middlewareChanges）
7. コンパイルエラーの通知（エラーオーバーレイ表示）

**関連システム・外部連携**：Webpack HMR、Turbopack HMR、Rspack HMR、React Fast Refresh、On-Demand Entry Handler、DevTools。

**権限による制御**：特になし。開発モードでのみ動作する。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 12 | 開発オーバーレイ (Dev Overlay) | 補助機能 | HMRメッセージに基づくUI更新 |
| 15 | ビルドエラー画面 | 補助機能 | コンパイルエラーのオーバーレイ表示 |
| 16 | ランタイムエラー画面 | 補助機能 | ランタイムエラーのオーバーレイ表示 |

## 機能種別

開発支援 / リアルタイムコンパイル / モジュール差し替え

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| ファイル変更イベント | FSWatcher | Yes | ファイルシステムの変更検知 | - |
| WebSocket接続 | ws.WebSocket | Yes | クライアントとの双方向通信 | - |
| webpack.MultiCompiler | MultiCompiler | No | Webpackの複数コンパイラ（Webpack HMR時） | - |
| TurbopackProject | Project | No | Turbopackプロジェクト（Turbopack HMR時） | - |

### 入力データソース

- ファイルシステム（ソースファイルの変更イベント）
- バンドラー（コンパイル完了イベント）
- WebSocket（クライアントからのping/pongメッセージ）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| HmrMessageSentToBrowser | union型 | ブラウザに送信されるHMRメッセージ群 |
| コンパイル済みモジュール | webpack.Stats | 更新されたモジュールのコンパイル結果 |

### 出力先

WebSocket経由でブラウザクライアントに送信される。

## 処理フロー

### 処理シーケンス

```
1. HotReloader初期化
   └─ WebSocketサーバーの起動
   └─ バンドラー（Webpack/Turbopack/Rspack）の設定
2. ファイル変更検知
   └─ バンドラーのwatch機能による検知
3. コンパイル開始
   └─ 'building'メッセージをブラウザに送信
4. コンパイル完了
   └─ 変更タイプの判定（client/server/middleware/serverComponent）
5. HMRメッセージ送信
   └─ 変更タイプに応じたメッセージをWebSocket経由で送信
6. クライアント側処理
   └─ React Fast Refreshによるコンポーネント差し替え
   └─ または全ページリロード
```

### フローチャート

```mermaid
flowchart TD
    A[ファイル変更検知] --> B[building メッセージ送信]
    B --> C[コンパイル実行]
    C --> D{コンパイル成功?}
    D -->|No| E[エラーメッセージ送信]
    D -->|Yes| F{変更タイプ}
    F -->|Client Changes| G[clientChanges メッセージ]
    F -->|Server Component| H[serverComponentChanges メッセージ]
    F -->|Middleware| I[middlewareChanges メッセージ]
    F -->|Server Only| J[serverOnlyChanges メッセージ]
    F -->|Page Added| K[addedPage メッセージ]
    F -->|Page Removed| L[removedPage メッセージ]
    G --> M[sync/built メッセージ]
    H --> M
    I --> N[ページリロード]
    J --> M
    K --> M
    L --> M
    E --> O[Dev Overlay表示]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-69-01 | マルチバンドラー対応 | Webpack、Turbopack、Rspackの3種類のバンドラーに対応するHotReloader実装を提供 | バンドラー設定に応じて |
| BR-69-02 | NextJsHotReloaderInterface | 全バンドラー共通のインターフェースを定義し、統一的なAPIを提供する | 常時 |
| BR-69-03 | メッセージ種別 | HMR_MESSAGE_SENT_TO_BROWSERで定義されるJSON/バイナリの2種類のメッセージ形式 | WebSocket通信時 |
| BR-69-04 | Legacy/Modernクライアント分離 | sendToLegacyClients()でPages Routerクライアントのみにメッセージを送信可能 | Cache Components非対応クライアント向け |
| BR-69-05 | Server Components HMR | serverComponentChangesメッセージでServer Componentsの変更を通知する | App Router使用時 |
| BR-69-06 | ミドルウェア変更 | ミドルウェアファイルの変更時はmiddlewareChangesメッセージを送信し、ページリロードを要求する | middleware.ts変更時 |

### 計算ロジック

特になし。

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| CompilationError | コンパイルエラー | ソースファイルに構文エラーがある場合 | syncメッセージのerrorsフィールドで通知し、Dev Overlayに表示 |
| ServerError | サーバーエラー | サーバーサイドでエラーが発生した場合 | serverErrorメッセージで通知 |
| InvariantError | 内部エラー | HotReloaderの不正な状態遷移 | エラーログ出力 |

### リトライ仕様

ファイル再保存時に自動的に再コンパイルが実行される。

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

該当なし。

## パフォーマンス要件

- 差分コンパイルにより、変更されたモジュールのみを再ビルドする
- WebSocket接続により低レイテンシーで更新を通知する
- On-Demand Entry Handlerとの連携により、アクセスされたページのみをコンパイルする

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

- HMRは開発環境でのみ動作し、本番環境では無効化される
- WebSocket接続はlocalhostに限定される

## 備考

- Webpack HMRは`hot-reloader-webpack.ts`、Turbopack HMRは`hot-reloader-turbopack.ts`、Rspack HMRは`hot-reloader-rspack.ts`に実装される
- 共通のインターフェースは`hot-reloader-types.ts`に定義される
- React Fast Refreshの統合により、コンポーネントの状態を保持したまま差し替えが可能

---

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

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

### 推奨読解順序

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

まず、HMRメッセージの型定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | hot-reloader-types.ts | `packages/next/src/server/dev/hot-reloader-types.ts` | HMR_MESSAGE_SENT_TO_BROWSERとHMR_MESSAGE_SENT_TO_SERVERの列挙型、各メッセージ型の定義 |

**読解のコツ**: HMR_MESSAGE_SENT_TO_BROWSERはenumで定義される。JSONメッセージ（文字列型）とバイナリメッセージ（数値型: 0, 1）の2種類がある。数値型のメッセージ（REACT_DEBUG_CHUNK=0、ERRORS_TO_SHOW_IN_BROWSER=1）はバイナリ形式で送信される。

#### Step 2: HotReloaderインターフェースを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | hot-reloader-types.ts | `packages/next/src/server/dev/hot-reloader-types.ts` | NextJsHotReloaderInterfaceの定義（219-281行目）。全バンドラー共通のAPIを確認 |

**主要処理フロー**:
- **224-228行目**: run()メソッド - リクエスト処理
- **232行目**: start()メソッド - HMRの開始
- **233行目**: send()メソッド - 全クライアントへのメッセージ送信
- **238行目**: sendToLegacyClients()メソッド - レガシークライアント専用送信
- **249行目**: getCompilationErrors()メソッド - コンパイルエラー取得
- **259-263行目**: invalidate()メソッド - コンパイル無効化と再ビルド
- **265-279行目**: ensurePage()メソッド - ページのコンパイル保証

#### Step 3: Webpack HMR実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | hot-reloader-webpack.ts | `packages/next/src/server/dev/hot-reloader-webpack.ts` | Webpack版HotReloader。on-demand-entry-handler、WebpackHotMiddleware、watchCompilersの統合 |

#### Step 4: Turbopack HMR実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | hot-reloader-turbopack.ts | `packages/next/src/server/dev/hot-reloader-turbopack.ts` | Turbopack版HotReloader。TurbopackProjectとの連携、changeSubscriptionsによるファイル監視 |

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

```
DevServer
    │
    └─ HotReloader (NextJsHotReloaderInterface)
           │
           ├─ hot-reloader-webpack.ts（Webpack実装）
           │      ├─ webpack.MultiCompiler
           │      ├─ WebpackHotMiddleware
           │      ├─ on-demand-entry-handler
           │      └─ watchCompilers()
           │
           ├─ hot-reloader-turbopack.ts（Turbopack実装）
           │      ├─ TurbopackProject
           │      ├─ changeSubscriptions
           │      ├─ handleEntrypoints()
           │      └─ handleRouteType()
           │
           └─ hot-reloader-rspack.ts（Rspack実装）
                  └─ Rspackコンパイラ

    WebSocket Server
           │
           ├─ send() → HmrMessageSentToBrowser
           ├─ sendToLegacyClients()
           └─ onHMR() → クライアント接続管理
```

### データフロー図

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

ファイル変更          ──▶  バンドラー（Webpack/Turbopack/Rspack）
                              │
                              ├─ コンパイル実行
                              │
                              ▼
                           HotReloader
                              │
                              ├─ 変更タイプ判定
                              │    ├─ client
                              │    ├─ serverComponent
                              │    ├─ middleware
                              │    └─ serverOnly
                              │
                              ▼
                           WebSocket Server  ──▶  HMRメッセージ ──▶ ブラウザ
                                                    │
                                                    ▼
                                              React Fast Refresh
                                              コンポーネント差し替え
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| hot-reloader-types.ts | `packages/next/src/server/dev/hot-reloader-types.ts` | ソース | HMRメッセージ型定義・インターフェース定義 |
| hot-reloader-webpack.ts | `packages/next/src/server/dev/hot-reloader-webpack.ts` | ソース | Webpack版HotReloader実装 |
| hot-reloader-turbopack.ts | `packages/next/src/server/dev/hot-reloader-turbopack.ts` | ソース | Turbopack版HotReloader実装 |
| hot-reloader-rspack.ts | `packages/next/src/server/dev/hot-reloader-rspack.ts` | ソース | Rspack版HotReloader実装 |
| hot-reloader-shared-utils.ts | `packages/next/src/server/dev/hot-reloader-shared-utils.ts` | ソース | HotReloader共通ユーティリティ |
| hot-middleware.ts | `packages/next/src/server/dev/hot-middleware.ts` | ソース | Webpack HotMiddleware |
| on-demand-entry-handler.ts | `packages/next/src/server/dev/on-demand-entry-handler.ts` | ソース | オンデマンドエントリーハンドラ |
