# 帳票設計書 17-interception-route-rewrite-manifest.js

## 概要

本ドキュメントは、Next.jsビルドプロセスにおいて生成される `interception-route-rewrite-manifest.js`（インターセプトルートリライトマニフェスト）の設計仕様を定義する。本マニフェストは、インターセプトルートのリライト情報をエッジランタイム向けに提供する。

### 本帳票の処理概要

本マニフェストは、Next.jsのインターセプトルート機能で使用されるリライトルールのうち、`beforeFiles` リライトに含まれるインターセプトルートリライトをフィルタリングし、エッジランタイムで利用可能なJavaScript形式で出力する。エッジランタイムにはルートマニフェスト全体へのアクセスがないため、インターセプトルートのリライト情報のみを切り出して提供する。

**業務上の目的・背景**：Next.jsのインターセプトルート（Intercepting Routes）は、App Routerの機能であり、モーダルなどのUI パターンで使用される。ユーザーがリンクをクリックした際に、別のルートのコンテンツを現在のレイアウト内に表示するためのリライトルールが必要となる。エッジランタイムで実行されるSSRはルートマニフェスト全体にアクセスできないため、インターセプトルートに必要なリライト情報のみを別途マニフェストとして提供する。

**帳票の利用シーン**：`next build` コマンド実行時に `MiddlewarePlugin` により自動生成される。Turbopack使用時は `TurbopackManifestLoader` の `writeInterceptionRouteRewriteManifest` メソッドにより生成される。エッジランタイムのSSRページがインターセプトルートのリライト処理を実行する際に参照される。

**主要な出力内容**：
1. インターセプトルートに該当するbeforeFilesリライトルールの配列
2. `self.__INTERCEPTION_ROUTE_REWRITE_MANIFEST` 変数としてのリライト情報

**帳票の出力タイミング**：Webpackコンパイルフェーズの `PROCESS_ASSETS_STAGE_ADDITIONS` ステージで `MiddlewarePlugin` により生成される。

**帳票の利用者**：エッジランタイムで実行されるNext.jsのSSRページ。クライアントサイドのルートローダー。

## 帳票種別

ビルドマニフェスト（JavaScript形式・エッジランタイム向け）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| N/A | CLIコマンド | `next build` | ビルド実行 |
| N/A | 開発サーバー | `next dev` | 開発サーバー起動 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | JavaScript (.js) |
| 用紙サイズ | N/A（データファイル） |
| 向き | N/A |
| ファイル名 | `interception-route-rewrite-manifest.js` |
| 出力方法 | ファイルシステムへの書き込み |
| 文字コード | UTF-8 |

### JavaScript形式

```javascript
self.__INTERCEPTION_ROUTE_REWRITE_MANIFEST="[{\"source\":\"/(.)photo/:id\",\"destination\":\"/photo/:id\",\"regex\":\"...\"}]"
```

## 帳票レイアウト

### レイアウト概要

インターセプトルートリライトルールの配列をJSON文字列としてJavaScript変数に格納する。

```
┌──────────────────────────────────────────────────────────────────┐
│  self.__INTERCEPTION_ROUTE_REWRITE_MANIFEST = JSON.stringify([  │
│    {                                                            │
│      source: string      // リライト元パス                       │
│      destination: string // リライト先パス                       │
│      regex: string       // マッチング正規表現                   │
│      ...                 // その他リライト設定                   │
│    }                                                            │
│  ])                                                             │
└──────────────────────────────────────────────────────────────────┘
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | source | リライト元パスパターン | beforeFilesリライト | 文字列 |
| 2 | destination | リライト先パス | beforeFilesリライト | 文字列 |
| 3 | regex | マッチング正規表現 | リライトルールから生成 | 文字列 |

### 明細部

N/A（リライトルール配列）

### フッター部

N/A

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| インターセプトルート存在 | beforeFilesリライトにインターセプトルートリライトが含まれること | No（空配列も出力） |
| isInterceptionRouteRewrite | リライトルールがインターセプトルートのリライトとして判定されること | Yes（フィルタ条件） |

### ソート順

N/A（beforeFilesリライトの定義順）

### 改ページ条件

N/A

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

N/A

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| インターセプトリライト抽出 | `rewrites.beforeFiles.filter(isInterceptionRouteRewrite)` | N/A | beforeFilesからインターセプトルートのみ抽出 |
| マニフェスト変換 | `self.__INTERCEPTION_ROUTE_REWRITE_MANIFEST=${JSON.stringify(JSON.stringify(filtered))}` | N/A | Webpack版。Turbopack版は末尾にセミコロン付き |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[ビルド実行] --> B{Webpack or Turbopack?}
    B -->|Webpack| C[MiddlewarePlugin]
    B -->|Turbopack| D[TurbopackManifestLoader]
    C --> E[beforeFilesリライト取得]
    D --> F[beforeFilesリライト取得]
    E --> G[isInterceptionRouteRewriteでフィルタ]
    F --> H[isInterceptionRouteRewriteでフィルタ]
    G --> I[JSON.stringify x 2]
    H --> J[JSON.stringify + セミコロン]
    I --> K[interception-route-rewrite-manifest.js出力]
    J --> K
    K --> L[終了]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| リライトなし | インターセプトルートリライトが存在しない | エラーなし（空配列のマニフェスト） | 対処不要 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | インターセプトルートの数に依存（通常数件） |
| 目標出力時間 | 即座（フィルタとJSON変換のみ） |
| 同時出力数上限 | 1 |

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

リライトルール情報のみを含み、機密情報は含まれない。ルーティング設定は公開情報として扱われる。

## 備考

- 定数名 `INTERCEPTION_ROUTE_REWRITE_MANIFEST` は `constants.ts` の135-136行目で定義（値: `'interception-route-rewrite-manifest'`）。
- Webpack版（MiddlewarePlugin）ではルートディレクトリに出力（`${INTERCEPTION_ROUTE_REWRITE_MANIFEST}.js`）。
- Turbopack版（TurbopackManifestLoader）では `server/` ディレクトリに出力（`server/${INTERCEPTION_ROUTE_REWRITE_MANIFEST}.js`）。
- `isInterceptionRouteRewrite` 関数は `lib/generate-interception-routes-rewrites.ts` で定義される。
- Turbopack版ではキャッシュ（`cachedInterceptionRewrites`）を使用し、変更がない場合は書き込みをスキップする。
- ミドルウェアプラグイン（middleware-plugin.ts 135行目）で、エッジSSRのファイルリストに本マニフェストが含まれる。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | constants.ts | `packages/next/src/shared/lib/constants.ts` | 135-136行目: `INTERCEPTION_ROUTE_REWRITE_MANIFEST` 定数 |

**読解のコツ**: マニフェストの内容はリライトルール（CustomRoutes['rewrites']のbeforeFiles）のサブセットである。

#### Step 2: Webpack生成処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | middleware-plugin.ts | `packages/next/src/build/webpack/plugins/middleware-plugin.ts` | 176-186行目: `getCreateAssets` 関数内。`beforeFiles` からインターセプトルートリライトをフィルタし、`compilation.emitAsset` で出力 |

**主要処理フロー**:
- **176-178行目**: `opts.rewrites.beforeFiles.filter(isInterceptionRouteRewrite)` でフィルタリング
- **179-186行目**: `compilation.emitAsset` で `${INTERCEPTION_ROUTE_REWRITE_MANIFEST}.js` を出力
- **182-184行目**: `self.__INTERCEPTION_ROUTE_REWRITE_MANIFEST=${JSON.stringify(interceptionRewrites)}` 形式

#### Step 3: Turbopack生成処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | manifest-loader.ts | `packages/next/src/shared/lib/turbopack/manifest-loader.ts` | 489-522行目: `writeInterceptionRouteRewriteManifest` メソッド。キャッシュ付きの書き込み処理 |

**主要処理フロー**:
- **500-501行目**: `rewrites.beforeFiles.filter(isInterceptionRouteRewrite)` でフィルタ
- **504-507行目**: キャッシュとの比較で変更なし時はスキップ
- **516-520行目**: `writeFileAtomic` で `server/${INTERCEPTION_ROUTE_REWRITE_MANIFEST}.js` を出力

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

```
next build
    |
    +-- [Webpack] MiddlewarePlugin
    |       |
    |       +-- getCreateAssets()
    |               +-- isInterceptionRouteRewrite() でフィルタ
    |               +-- compilation.emitAsset()
    |
    +-- [Turbopack] TurbopackManifestLoader.writeManifests()
            |
            +-- writeInterceptionRouteRewriteManifest()
                    +-- isInterceptionRouteRewrite() でフィルタ
                    +-- writeFileAtomic()
```

### データフロー図

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

next.config.js rewrites    MiddlewarePlugin /                   .next/server/interception-route-rewrite-manifest.js
  beforeFiles[]        --> TurbopackManifestLoader          -->
                           isInterceptionRouteRewrite()
                           でフィルタリング

                           エッジランタイム                     __INTERCEPTION_ROUTE_REWRITE_MANIFEST
  manifest.js          --> (グローバル変数参照)              --> リライト処理
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| middleware-plugin.ts | `packages/next/src/build/webpack/plugins/middleware-plugin.ts` | ソース | Webpack版のマニフェスト生成 |
| manifest-loader.ts | `packages/next/src/shared/lib/turbopack/manifest-loader.ts` | ソース | Turbopack版のマニフェスト生成 |
| constants.ts | `packages/next/src/shared/lib/constants.ts` | ソース | 定数定義 |
| generate-interception-routes-rewrites.ts | `packages/next/src/lib/generate-interception-routes-rewrites.ts` | ソース | `isInterceptionRouteRewrite` 関数定義 |
| route-loader.ts | `packages/next/src/client/route-loader.ts` | ソース | クライアント `__INTERCEPTION_ROUTE_REWRITE_MANIFEST` 参照 |
| route-module.ts | `packages/next/src/server/route-modules/route-module.ts` | ソース | サーバーモジュールでの参照 |
