# 帳票設計書 5-routes-manifest.json

## 概要

本ドキュメントは、Next.jsビルドプロセスにおいて生成される `routes-manifest.json` の設計を記述する。このマニフェストは、静的ルート・動的ルート・リダイレクト・リライト・ヘッダーの定義を一元的に管理するルーティングマニフェストである。

### 本帳票の処理概要

routes-manifest.json は、`generateRoutesManifest` 関数によって生成されるJSONファイルである。アプリケーションの全ルーティング設定（静的ルート、動的ルート、リダイレクト、リライト、ヘッダー、国際化設定、RSC設定等）を包含し、Next.jsサーバーおよびデプロイメントプラットフォームがルーティングを処理するための中核的な設計情報を提供する。

**業務上の目的・背景**：Next.jsアプリケーションのルーティングは、ファイルシステムベースのページルートに加えて、`next.config.js`で定義されるリダイレクト・リライト・ヘッダーのカスタムルートを含む。これらのルーティング情報を統合的に管理し、サーバーランタイムやCDN/エッジネットワークが効率的にルーティング処理を行えるようにすることが本マニフェストの目的である。

**帳票の利用シーン**：本番サーバー起動時のルーティングテーブル構築、Vercel等のデプロイメントプラットフォームでのルーティング設定、ミドルウェア処理前のルート判定、i18n対応のURL処理に使用される。

**主要な出力内容**：
1. `staticRoutes` - 静的ルートのリスト（正規表現付き）
2. `dynamicRoutes` - 動的ルートのリスト（正規表現・名前付きパラメータ付き）
3. `redirects` - リダイレクトルールのリスト
4. `rewrites` - リライトルール（beforeFiles/afterFiles/fallback）
5. `headers` - カスタムヘッダールールのリスト
6. `i18n` - 国際化設定
7. `rsc` - React Server Components関連のヘッダー・サフィックス設定
8. `ppr` - Partial Prerendering設定

**帳票の出力タイミング**：`next build` コマンド実行時、ビルドプロセスの中で `generateRoutesManifest` が呼び出された際に生成される。

**帳票の利用者**：Next.jsサーバーランタイム、デプロイメントプラットフォーム（Vercel等）、CDN/エッジネットワーク、ビルドプロセス内の各種解析処理。

## 帳票種別

ビルドマニフェスト（JSON形式のルーティング設定ファイル）

## 利用画面

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

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | JSON |
| 用紙サイズ | N/A（データファイル） |
| 向き | N/A |
| ファイル名 | `routes-manifest.json` |
| 出力方法 | ファイルシステムへの書き出し（`.next/routes-manifest.json`） |
| 文字コード | UTF-8 |

### PDF固有設定

N/A

### Excel固有設定

N/A

## 帳票レイアウト

### レイアウト概要

routes-manifest.json は、ルーティングに必要な全情報を含むJSONオブジェクトである。

```
{
  "version": 3,
  "pages404": true,
  "appType": "hybrid",
  "caseSensitive": false,
  "basePath": "",
  "redirects": [...],
  "headers": [...],
  "rewrites": {
    "beforeFiles": [...],
    "afterFiles": [...],
    "fallback": [...]
  },
  "dynamicRoutes": [...],
  "staticRoutes": [...],
  "dataRoutes": [],
  "i18n": {...},
  "rsc": {...},
  "ppr": {...}
}
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | version | マニフェストバージョン | 固定値 `3` | 数値 |
| 2 | pages404 | 404ページの有無 | 固定値 `true` | 真偽値 |
| 3 | appType | アプリケーション種別 | `options.appType`（`pages`/`app`/`hybrid`） | 文字列 |
| 4 | caseSensitive | 大文字小文字区別 | `config.experimental.caseSensitiveRoutes` | 真偽値 |
| 5 | basePath | ベースパス | `config.basePath` | 文字列 |

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | staticRoutes | 静的ルートのリスト | `sortedRoutes` のうち `isDynamicRoute` が false のもの | オブジェクト配列 | N/A |
| 2 | dynamicRoutes | 動的ルートのリスト | `sortedRoutes` のうち `isDynamicRoute` が true のもの | オブジェクト配列 | N/A |
| 3 | redirects | リダイレクトルール | `options.redirects` を `buildCustomRoute('redirect', ...)` で変換 | オブジェクト配列 | N/A |
| 4 | headers | カスタムヘッダールール | `options.headers` を `buildCustomRoute('header', ...)` で変換 | オブジェクト配列 | N/A |
| 5 | rewrites.beforeFiles | ファイル前リライト | `options.rewrites.beforeFiles` を `buildCustomRoute('rewrite', ...)` で変換 | オブジェクト配列 | N/A |
| 6 | rewrites.afterFiles | ファイル後リライト | `options.rewrites.afterFiles` | オブジェクト配列 | N/A |
| 7 | rewrites.fallback | フォールバックリライト | `options.rewrites.fallback` | オブジェクト配列 | N/A |
| 8 | dataRoutes | データルート | 初期値空配列（後で設定） | 配列 | N/A |
| 9 | i18n | 国際化設定 | `config.i18n` | オブジェクト/undefined | N/A |

### フッター部（RSC・PPR設定）

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | rsc.header | RSCヘッダー名 | `RSC_HEADER` 定数 | 文字列 |
| 2 | rsc.varyHeader | RSC Varyヘッダー | RSC関連ヘッダーの結合 | 文字列 |
| 3 | rsc.prefetchHeader | プリフェッチヘッダー名 | `NEXT_ROUTER_PREFETCH_HEADER` 定数 | 文字列 |
| 4 | rsc.suffix | RSCサフィックス | `RSC_SUFFIX` 定数 | 文字列 |
| 5 | ppr | Partial Prerendering設定 | `isAppPPREnabled`に応じて設定 | オブジェクト/undefined |
| 6 | deploymentId | デプロイメントID | `options.deploymentId` | 文字列/undefined |
| 7 | skipProxyUrlNormalize | プロキシURL正規化スキップ | `config.skipProxyUrlNormalize` | 真偽値 |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| ページキー | PagesルーターとApp Routerのページキーが入力される | Yes |
| カスタムルート | next.config.jsのredirects/rewrites/headersが入力される | No |
| 予約ページ除外 | `isReservedPage` でフィルタ（ただし `/api` は除外しない） | Yes |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | ルート（sortPages使用） | Next.js独自のソート順 |

### 改ページ条件

N/A

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

N/A

### テーブル別参照項目詳細

N/A

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| staticRoutes | `sortedRoutes.filter(!isDynamicRoute && (!isReservedPage || /api/))` → `pageToRoute()` | N/A | 各ルートはpageToRouteで正規表現付きオブジェクトに変換 |
| dynamicRoutes | `sortedRoutes.filter(isDynamicRoute)` → `pageToRoute()` | N/A | 動的パラメータの正規表現を含む |
| redirects | `redirects.map(r => buildCustomRoute('redirect', r, restrictedRedirectPaths))` | N/A | restrictedRedirectPathsで内部パスへのリダイレクトを制限 |
| rsc.varyHeader | `${RSC_HEADER}, ${NEXT_ROUTER_STATE_TREE_HEADER}, ${NEXT_ROUTER_PREFETCH_HEADER}, ${NEXT_ROUTER_SEGMENT_PREFETCH_HEADER}` | N/A | 結合文字列 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[next build実行] --> B[ページキー・設定情報の収集]
    B --> C[generateRoutesManifest呼び出し]
    C --> D[sortPages でルートをソート]
    D --> E[各ルートをstatic/dynamicに分類]
    E --> F[redirects/headers/rewritesをbuildCustomRouteで変換]
    F --> G[i18n/rsc/ppr設定を構築]
    G --> H[RoutesManifestオブジェクト構築]
    H --> I[.next/routes-manifest.jsonに出力]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| 不正なリダイレクト | restrictedRedirectPathsに該当するリダイレクト | buildCustomRoute内でのバリデーション | next.config.jsのredirects設定を修正 |
| 不正なルートパターン | 正規表現に変換できないルートパス | ルートパターンのバリデーションエラー | ページパスの修正 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | ルート数 + カスタムルール数に依存 |
| 目標出力時間 | ルートソート・変換のため数ミリ秒〜数十ミリ秒 |
| 同時出力数上限 | 1 |

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

routes-manifest.jsonにはアプリケーションの全ルーティング構造、リダイレクトルール、リライトルールが含まれる。内部APIエンドポイントやリライト先の外部URLが露出する可能性があるため、`.next/` ディレクトリの外部非公開が重要。

## 備考

- version 3 が現在のマニフェストバージョン
- `dataRoutes` フィールドは初期値として空配列が設定され、ビルド後処理で更新される場合がある
- `rsc.clientParamParsing` は `config.cacheComponents` に基づく
- `rsc.dynamicRSCPrerender` は PPR有効かつ `cacheComponents === true` の場合にtrue
- `rewriteHeaders` で `NEXT_REWRITTEN_PATH_HEADER` と `NEXT_REWRITTEN_QUERY_HEADER` が設定される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | generate-routes-manifest.ts | `packages/next/src/build/generate-routes-manifest.ts` | `GenerateRoutesManifestOptions`型（26〜39行目）、`GenerateRoutesManifestResult`型（41〜45行目） |
| 1-2 | index.ts | `packages/next/src/build/index.ts` | `RoutesManifest`型（importで参照） |
| 1-3 | constants.ts | `packages/next/src/shared/lib/constants.ts` | `ROUTES_MANIFEST`定数（98行目） |

**読解のコツ**: RoutesManifest型はbuild/index.tsでexportされている型定義を参照。routes-manifestはNext.jsの中で最も情報量の多いマニフェストの一つ。

#### Step 2: 生成ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | generate-routes-manifest.ts | `packages/next/src/build/generate-routes-manifest.ts` | `generateRoutesManifest`関数（52〜156行目）。ルートの分類、カスタムルートの変換、RSC設定の構築 |

**主要処理フロー**:
1. **67行目**: `sortPages` でルートをソート
2. **77〜93行目**: 各ルートを `isDynamicRoute` で静的/動的に分類
3. **95〜149行目**: `RoutesManifest` オブジェクトの構築
4. **101〜103行目**: redirects/headers を `buildCustomRoute` で変換
5. **118〜133行目**: RSC設定の構築
6. **140〜148行目**: PPR設定の構築

#### Step 3: ヘッダー定数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | app-router-headers.ts | `packages/next/src/client/components/app-router-headers.ts` | RSC_HEADER, NEXT_ROUTER_STATE_TREE_HEADER等のヘッダー定数定義 |

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

```
next build (build/index.ts)
    |
    +-- generateRoutesManifest() [generate-routes-manifest.ts:52]
            |
            +-- sortPages()
            |       (packages/next/src/shared/lib/router/utils/sortable-routes.ts)
            |
            +-- isDynamicRoute()
            |       (packages/next/src/shared/lib/router/utils/index.ts)
            |
            +-- pageToRoute() / isReservedPage()
            |       (packages/next/src/build/utils.ts)
            |
            +-- buildCustomRoute()
            |       (packages/next/src/lib/build-custom-route.ts)
            |
            +-- writeManifest → .next/routes-manifest.json
```

### データフロー図

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

pageKeys (pages + app) ----------> generateRoutesManifest()
next.config.js (redirects,          |
  rewrites, headers, i18n) ------> ルート分類・変換 ----------------> .next/routes-manifest.json
config.experimental設定 ----------> RSC/PPR設定構築
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| generate-routes-manifest.ts | `packages/next/src/build/generate-routes-manifest.ts` | ソース | generateRoutesManifest関数の実装 |
| index.ts | `packages/next/src/build/index.ts` | ソース | ビルドプロセスからの呼び出し |
| constants.ts | `packages/next/src/shared/lib/constants.ts` | ソース | ROUTES_MANIFEST定数 |
| app-router-headers.ts | `packages/next/src/client/components/app-router-headers.ts` | ソース | RSCヘッダー定数群 |
| build-custom-route.ts | `packages/next/src/lib/build-custom-route.ts` | ソース | カスタムルートのビルド処理 |
| utils.ts | `packages/next/src/build/utils.ts` | ソース | pageToRoute, isReservedPage関数 |
| sortable-routes.ts | `packages/next/src/shared/lib/router/utils/sortable-routes.ts` | ソース | sortPages関数 |
| adapter/build-complete.ts | `packages/next/src/build/adapter/build-complete.ts` | ソース | アダプターでのroutes-manifest利用 |
| analyze/index.ts | `packages/next/src/build/analyze/index.ts` | ソース | バンドル解析でのroutes-manifest利用 |
