# 機能設計書 91-Segment Config

## 概要

本ドキュメントは、Next.jsのSegment Config機能の設計について記述する。Segment Configは、ルートセグメント単位でビルド・ランタイム設定を宣言的に制御するための仕組みであり、App Router / Pages Router / Middleware それぞれに対応した設定スキーマを提供する。

### 本機能の処理概要

**業務上の目的・背景**：Next.jsでは、各ルートセグメント（ページ、レイアウト、ルートハンドラー）が異なるレンダリング戦略やキャッシュ戦略を必要とする。Segment Configは、開発者がファイル内でexportする設定値を通じて、セグメント単位でランタイム（Edge/Node.js）、再検証間隔、動的レンダリング挙動などを宣言的に制御できるようにする。

**機能の利用シーン**：ルートセグメント設定は以下のような場面で利用される。
- ページ/レイアウトファイルで `export const dynamic = 'force-dynamic'` のようにエクスポートし、動的レンダリングを強制する場合
- `export const revalidate = 60` で ISR の再検証間隔を指定する場合
- `export const runtime = 'edge'` で Edge Runtime を選択する場合
- Middleware の `config` オブジェクトでマッチャーパターンを定義する場合

**主要な処理内容**：
1. Zod スキーマによる設定値のバリデーション（App Router / Pages Router / Middleware 各スキーマ）
2. ルートモジュールのユーザーランドエクスポートからの設定値パース
3. ローダーツリーを走査してセグメント情報（パラメータ名、型、ファイルパス、generateStaticParams）を収集
4. ルートパラメータキーの収集（ルートレイアウトまでの動的セグメントパラメータ抽出）

**関連システム・外部連携**：ビルドシステム（Webpack/Turbopack）、App Renderパイプライン、Pages Routerレンダリングパイプラインと連携する。

**権限による制御**：Server Components のみが Segment Config を設定可能。Client Components（`use client`）からの設定は無視される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | Segment Configは画面を持たないビルド時設定機能 |

## 機能種別

バリデーション / 設定解析処理

## 入力仕様

### 入力パラメータ

#### App Router Segment Config

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| revalidate | number \| false | No | ISR再検証間隔（秒）またはfalseで無効化 | 非負整数またはfalse |
| dynamicParams | boolean | No | 動的パラメータの許可/禁止 | boolean |
| dynamic | string | No | 動的レンダリングの挙動制御 | 'auto' \| 'error' \| 'force-static' \| 'force-dynamic' |
| fetchCache | string | No | fetchキャッシュ戦略 | 'auto' \| 'default-cache' \| 'only-cache' \| 'force-cache' \| 'force-no-store' \| 'default-no-store' \| 'only-no-store' |
| unstable_prefetch | object | No | プリフェッチ設定 | mode: 'static' \| 'runtime' の識別子付きオブジェクト |
| preferredRegion | string \| string[] | No | 優先リージョン | 文字列または文字列配列 |
| runtime | string | No | ランタイム選択 | 'edge' \| 'nodejs' |
| maxDuration | number | No | 最大実行時間（秒） | 非負整数 |

#### Pages Router Segment Config

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| runtime | string | No | ランタイム選択 | 'edge' \| 'experimental-edge' \| 'nodejs' |
| maxDuration | number | No | 最大実行時間 | number |
| config | object | No | ネストされた設定オブジェクト | runtime, maxDuration を含むオブジェクト |

#### Middleware Config

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| matcher | string \| Array | No | URLマッチャーパターン | ソースパスは `/` 始まり、4096文字以下 |
| regions | string \| string[] | No | 実行リージョン | 文字列または文字列配列 |
| unstable_allowDynamic | string \| string[] | No | 動的コード評価を許可するglob | 有効なglobパターン |

### 入力データソース

各ルートセグメントファイル（page.tsx, layout.tsx, route.ts, middleware.ts）からのexport値。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| AppSegmentConfig | object | パース済みApp Router設定 |
| PagesSegmentConfig | object | パース済みPages Router設定 |
| AppSegment[] | array | セグメント情報（名前、パラメータ、ファイルパス、設定、generateStaticParams）の配列 |
| rootParamKeys | string[] | ルートレイアウトまでの動的パラメータキー配列 |

### 出力先

ビルドパイプライン内部で使用（メモリ上のデータ構造としてビルド処理に渡される）。

## 処理フロー

### 処理シーケンス

```
1. ルートモジュールの読み込み
   └─ userland exportからデータを取得
2. Zodスキーマによるバリデーション
   └─ safeParse で安全に解析、エラー時は詳細メッセージ付きで例外送出
3. App Routerの場合: ローダーツリーの走査
   └─ BFSでパラレルルートを含む全セグメントを収集
4. 各セグメントの設定抽出
   └─ Server Componentのみ設定を読み取り、Client Componentはスキップ
5. generateStaticParamsの検出と検証
   └─ Edge Runtimeとの組み合わせはエラー
```

### フローチャート

```mermaid
flowchart TD
    A[ルートモジュール読み込み] --> B{モジュール種別判定}
    B -->|AppPageRouteModule| C[collectAppPageSegments]
    B -->|AppRouteRouteModule| D[collectAppRouteSegments]
    B -->|PagesModule| E[parsePagesSegmentConfig]
    B -->|Middleware| F[MiddlewareConfigInput解析]
    C --> G[ローダーツリーBFS走査]
    G --> H{Client Component?}
    H -->|Yes| I[設定スキップ]
    H -->|No| J[parseAppSegmentConfig]
    J --> K[Zodバリデーション]
    K -->|Success| L[セグメント情報構築]
    K -->|Failure| M[エラー送出]
    D --> N[パス分割によるセグメント生成]
    N --> J
    L --> O[セグメント配列返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | Server Componentのみ設定可能 | Client Componentからのsegment configエクスポートは無視される | App Routerのセグメント設定時 |
| BR-02 | Edge Runtime + generateStaticParams禁止 | runtime: 'edge' と generateStaticParams の併用は不可 | App Routerでの静的パス生成設定時 |
| BR-03 | Middlewareソースパス制約 | matcher のソースパスは `/` で始まり4096文字以下 | Middleware設定時 |
| BR-04 | 重複セグメント排除 | パラレルルートで同一セグメントが複数回出現する場合、最初の一つのみ採用 | App Routerのセグメント収集時 |

### 計算ロジック

特になし。

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

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

該当なし（データベースは使用しない）。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ZodValidationError | revalidateに無効な値（負の数等）を指定 | エラーメッセージに設定ドキュメントURLを含めて送出 |
| - | ZodValidationError | dynamicに無効な文字列を指定 | 許可された列挙値をエラーメッセージに表示 |
| - | RuntimeError | Edge RuntimeとgenerateStaticParamsを併用 | 「Edge runtime is not supported with generateStaticParams」エラー |
| - | InvariantError | ルートモジュール種別が不正 | 内部エラーとして送出 |
| - | ZodValidationError | Middlewareのソースパスが不正 | パスの形式エラーを詳細に表示 |

### リトライ仕様

リトライは不要（ビルド時の静的解析処理のため）。

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

該当なし。

## パフォーマンス要件

ビルド時に全ルートセグメントを走査するため、セグメント数に比例した処理時間となる。通常のプロジェクトでは数十〜数百のセグメントであり、パフォーマンス上の問題は発生しない。

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

- ユーザーが設定ファイルに不正な値を入力した場合、Zodスキーマによりバリデーションされ、ビルドエラーとして安全に処理される。
- ランタイム設定（Edge / Node.js）の選択はセキュリティ境界に影響するため、正しくバリデーションされる。

## 備考

- `unstable_prefetch` はexperimental機能であり、将来的にAPIが変更される可能性がある。
- Pages Routerでは `experimental-edge` ランタイムも許容されるが、App Routerでは `edge` と `nodejs` のみ。

---

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

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

### 推奨読解順序

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

まず、各ルーター向けの設定スキーマと型定義を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | app-segment-config.ts | `packages/next/src/build/segment-config/app/app-segment-config.ts` | AppSegmentConfig型とZodスキーマの定義。revalidate, dynamic, runtime等の設定項目を理解する |
| 1-2 | pages-segment-config.ts | `packages/next/src/build/segment-config/pages/pages-segment-config.ts` | PagesSegmentConfig型とZodスキーマ。Pages Router固有のconfig入れ子構造を理解する |
| 1-3 | middleware-config.ts | `packages/next/src/build/segment-config/middleware/middleware-config.ts` | MiddlewareConfigInput型。matcher, regions, unstable_allowDynamicの構造を理解する |

**読解のコツ**: Zodスキーマは型定義と実行時バリデーションの両方を兼ねている。`z.object()`の各フィールドのバリデーションルール（`.optional()`, `.nonnegative()`, `.enum()`等）に注目すること。

#### Step 2: エントリーポイントを理解する

設定のパースと収集を行うメインの関数を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | app-segments.ts | `packages/next/src/build/segment-config/app/app-segments.ts` | collectSegments関数がエントリーポイント。AppRouteとAppPageで処理を分岐する |

**主要処理フロー**:
1. **175-189行目**: `collectSegments`関数がルートモジュール種別を判定して適切な収集関数にディスパッチ
2. **72-126行目**: `collectAppPageSegments`がBFS方式でローダーツリーを走査し、各セグメントの情報を収集
3. **134-167行目**: `collectAppRouteSegments`がパス名を分割してセグメント配列を生成

#### Step 3: 設定のアタッチ処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | app-segments.ts | `packages/next/src/build/segment-config/app/app-segments.ts` | attach関数（27-55行目）がセグメントに設定を付与する |

**主要処理フロー**:
- **27-31行目**: userlandがオブジェクトでない場合は早期リターン
- **34行目**: parseAppSegmentConfigでバリデーション
- **41-53行目**: generateStaticParamsの検出とEdge Runtime制約の検証

#### Step 4: ルートパラメータキー収集を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | collect-root-param-keys.ts | `packages/next/src/build/segment-config/app/collect-root-param-keys.ts` | ルートレイアウトまでの動的パラメータを収集する処理 |

**主要処理フロー**:
- **10-39行目**: `collectAppPageRootParamKeys`がローダーツリーを先頭から走査し、最初のlayoutモジュールが見つかるまでの動的セグメントパラメータを収集

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

```
collectSegments (app-segments.ts:175)
    │
    ├─ collectAppPageSegments (app-segments.ts:72)
    │      ├─ getLayoutOrPageModule (app-dir-module.ts)
    │      ├─ isClientReference (client-and-server-references.ts)
    │      ├─ getSegmentParam (get-segment-param.ts)
    │      └─ attach (app-segments.ts:27)
    │             └─ parseAppSegmentConfig (app-segment-config.ts:154)
    │                    └─ AppSegmentConfigSchema.safeParse (zod)
    │
    └─ collectAppRouteSegments (app-segments.ts:134)
           ├─ getSegmentParam (get-segment-param.ts)
           └─ attach (app-segments.ts:27)

collectRootParamKeys (collect-root-param-keys.ts:47)
    └─ collectAppPageRootParamKeys (collect-root-param-keys.ts:10)
           └─ getSegmentParam (get-segment-param.ts)
```

### データフロー図

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

ルートモジュール ───────▶ collectSegments ──────────▶ AppSegment[]
(userland exports)         │
                           ├─ parseAppSegmentConfig ─▶ AppSegmentConfig
                           │     └─ Zod safeParse
                           │
Middlewareモジュール ────▶ MiddlewareConfigInputSchema ──▶ MiddlewareConfigInput
(config export)             └─ Zod safeParse
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| app-segment-config.ts | `packages/next/src/build/segment-config/app/app-segment-config.ts` | ソース | App Router用Segment Configスキーマ・パース関数 |
| app-segments.ts | `packages/next/src/build/segment-config/app/app-segments.ts` | ソース | App Routerセグメント収集・設定アタッチ |
| collect-root-param-keys.ts | `packages/next/src/build/segment-config/app/collect-root-param-keys.ts` | ソース | ルートパラメータキー収集 |
| pages-segment-config.ts | `packages/next/src/build/segment-config/pages/pages-segment-config.ts` | ソース | Pages Router用Segment Configスキーマ・パース関数 |
| middleware-config.ts | `packages/next/src/build/segment-config/middleware/middleware-config.ts` | ソース | Middleware用設定スキーマ |
| get-segment-param.ts | `packages/next/src/shared/lib/router/utils/get-segment-param.ts` | ソース | セグメント名から動的パラメータを抽出 |
| app-dir-module.ts | `packages/next/src/server/lib/app-dir-module.ts` | ソース | ローダーツリーからモジュールを取得 |
| zod.ts | `packages/next/src/shared/lib/zod.ts` | ソース | Zodエラーフォーマットユーティリティ |
