# 帳票設計書 3-app-paths-manifest.json

## 概要

本ドキュメントは、Next.jsビルドプロセスにおいて生成される `app-paths-manifest.json` の設計を記述する。このマニフェストは、App Router用のルートパスとサーバー側のJavaScriptファイルパスの対応関係を管理する。

### 本帳票の処理概要

app-paths-manifest.json は、Next.jsのWebpackビルドにおいて `PagesManifestPlugin` によって生成されるJSONファイルである。App Router（`app/` ディレクトリ）配下の各ルートについて、ルートパスとサーバー側のJSファイルへのマッピングを提供する。pages-manifest.jsonのApp Router版として機能する。

**業務上の目的・背景**：Next.js 13以降のApp Routerでは、`app/` ディレクトリ内の `page.tsx`, `route.ts` 等のファイルがルートを構成する。これらのApp Routerルートは、Pagesルーターのルートとは異なるエントリポイント構造を持つため、専用のマニフェストで管理される。サーバーがApp Routerのリクエストを処理する際、このマニフェストを参照してコンポーネントファイルを解決する。

**帳票の利用シーン**：App Routerを使用するアプリケーションのSSR時に、リクエストURLに対応するサーバーサイドJSファイルの解決に使用される。また、`app-path-routes-manifest.json` の生成元データとしても利用される。

**主要な出力内容**：
1. App Routerのルートパス（`app/` プレフィックス付き）とサーバー側JSファイルパスのキー・値ペア
2. Node.jsサーバーとEdgeサーバー双方のApp Routerエントリをマージした統合マニフェスト

**帳票の出力タイミング**：`next build` コマンド実行時のWebpackコンパイルプロセス中、`PROCESS_ASSETS_STAGE_ADDITIONS` ステージでPagesManifestPluginが実行された際に出力される。`appDirEnabled` が true の場合のみ生成される。

**帳票の利用者**：Next.jsサーバーランタイム（App Routerコンポーネントのロード）、ビルドプロセス（app-path-routes-manifest生成の入力データ）。

## 帳票種別

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

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| N/A | CLIコマンド | `next build` | ビルドコマンド実行 |
| N/A | 開発サーバー | `next dev` | 開発サーバー起動・ファイル変更時自動生成 |

## 出力形式

### 基本仕様

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

### PDF固有設定

N/A（JSON形式のため該当なし）

### Excel固有設定

N/A（JSON形式のため該当なし）

## 帳票レイアウト

### レイアウト概要

app-paths-manifest.json はフラットなJSONオブジェクトとして構成される。

```
{
  "/page": "app/page.js",
  "/about/page": "app/about/page.js",
  "/api/hello/route": "app/api/hello/route.js",
  "/dashboard/layout": "app/dashboard/layout.js"
}
```

### ヘッダー部

N/A（フラットなKey-Valueマッピング）

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | ルートパス（キー） | App Routerのルートパス | `getRouteFromEntrypoint(entrypoint.name, appDirEnabled=true)` の返却値 | 文字列 | N/A |
| 2 | ファイルパス（値） | サーバー側JSファイルの相対パス | エントリポイントの最後の`.js`ファイル | 文字列 | N/A |

### フッター部

N/A

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| App Router有効 | `appDirEnabled` が true の場合のみ生成 | Yes |
| App Routerエントリ判定 | `entrypoint.name` が `app/` で始まるエントリのみ対象 | Yes |
| ファイル形式フィルタ | webpack-runtime除外、`.js`ファイルのみ | Yes |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| N/A | ソート指定なし | エントリポイント処理順 |

### 改ページ条件

N/A

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

N/A（Webpackコンパイル結果から取得）

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

N/A

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| ファイルパス正規化 | `normalizePathSep(file)` | N/A | Windows互換性 |
| パススライス | 本番・Node.js時: `file.slice(3)` | N/A | ディレクトリ相対パス調整 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[Webpackコンパイル開始] --> B[PagesManifestPlugin.apply]
    B --> C[createAssets実行]
    C --> D[エントリポイント一覧をイテレート]
    D --> E{entrypoint.nameがapp/で始まるか?}
    E -->|Yes| F[appPathsに追加]
    E -->|No| G[pages-manifest用に処理]
    F --> H{Edgeランタイムか?}
    H -->|Yes| I[edgeServerAppPathsに保存]
    H -->|No| J[nodeServerAppPathsに保存]
    I --> K{appDirEnabledか?}
    J --> K
    K -->|Yes| L[edgeServerAppPathsとnodeServerAppPathsをマージ]
    K -->|No| M[出力なし]
    L --> N{distDirが指定されているか?}
    N -->|Yes| O[writeMergedManifestでファイル出力]
    N -->|No| P[compilation.emitAssetで出力]
    O --> Q[終了]
    P --> Q
    M --> Q
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| エントリ不在 | getRouteFromEntrypointがnullを返した場合 | N/A（スキップ） | エントリポイント設定の確認 |
| appDirEnabled=false | App Routerが無効の場合 | N/A（ファイル未生成） | next.config.jsのappDir設定確認 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | App Routerのルート数に依存 |
| 目標出力時間 | Webpackコンパイル時間内 |
| 同時出力数上限 | 1 |

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

pages-manifest.jsonと同様、サーバー側ファイルパスが含まれるため、`.next/server/` ディレクトリの外部非公開が必要。

## 備考

- PagesManifestPluginがpages-manifest.jsonとapp-paths-manifest.jsonの両方を生成する
- App Routerが有効でない場合、本ファイルは生成されない
- ビルドプロセス後半で本マニフェストを読み込み、`app-path-routes-manifest.json` を生成する（build/index.ts 2136〜2147行目）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | pages-manifest-plugin.ts | `packages/next/src/build/webpack/plugins/pages-manifest-plugin.ts` | `PagesManifest`型（11行目）。app-paths-manifest.jsonも同じ型を使用 |
| 1-2 | constants.ts | `packages/next/src/shared/lib/constants.ts` | `APP_PATHS_MANIFEST`定数（89行目） |

**読解のコツ**: app-paths-manifest.jsonはpages-manifest.jsonと同じ`PagesManifest`型（`{ [page: string]: string }`）を共有している。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | pages-manifest-plugin.ts | `packages/next/src/build/webpack/plugins/pages-manifest-plugin.ts` | `createAssets`メソッド（46〜178行目）。84〜88行目でapp/プレフィックスのエントリをappPathsに振り分ける処理 |

**主要処理フロー**:
1. **49行目**: `appPaths: PagesManifest = {}` で初期化
2. **84行目**: `entrypoint.name.startsWith('app/')` でApp Routerエントリを判別
3. **85行目**: `appPaths[pagePath] = file` でマッピング追加
4. **95行目**: Edgeランタイム時は `edgeServerAppPaths` に保存
5. **98行目**: Node.jsランタイム時は `nodeServerAppPaths` に保存

#### Step 3: 出力処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | pages-manifest-plugin.ts | `packages/next/src/build/webpack/plugins/pages-manifest-plugin.ts` | 152〜178行目。`appDirEnabled`がtrueの場合のみ出力処理が実行される |

**主要処理フロー**:
- **152行目**: `if (this.appDirEnabled)` で出力条件を確認
- **153〜161行目**: distDir指定時のファイル書き出し
- **163〜177行目**: distDir未指定時のcompilation.emitAsset

#### Step 4: ビルドプロセスでの利用を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | index.ts | `packages/next/src/build/index.ts` | 2133〜2147行目。app-paths-manifestを読み込み、app-path-routes-manifestを生成する処理 |

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

```
next build
    |
    +-- Webpack compilation
            |
            +-- PagesManifestPlugin.apply() [181行目]
                    |
                    +-- createAssets() [46行目]
                            |
                            +-- entrypoint分類 (app/ → appPaths)
                            |
                            +-- Edge/Node分離
                            |
                            +-- compilation.emitAsset / writeMergedManifest
                                    → .next/server/app-paths-manifest.json
    |
    +-- ビルド後処理 (build/index.ts)
            |
            +-- readManifest(app-paths-manifest.json) [2136行目]
            |
            +-- normalizeAppPath() で変換 [2141行目]
            |
            +-- writeManifest(app-path-routes-manifest.json) [2144行目]
```

### データフロー図

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

Webpack entrypoints            PagesManifestPlugin.createAssets
  (app/ prefixed entries) ---> edgeServerAppPaths/nodeServerAppPaths
                                    |                               .next/server/app-paths-manifest.json
                                    +-- マージ・出力

                               ビルド後処理 (build/index.ts)
app-paths-manifest.json -----> normalizeAppPath変換 ------------>  .next/app-path-routes-manifest.json
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| pages-manifest-plugin.ts | `packages/next/src/build/webpack/plugins/pages-manifest-plugin.ts` | ソース | PagesManifestPlugin実装（app-paths-manifest生成を含む） |
| constants.ts | `packages/next/src/shared/lib/constants.ts` | ソース | APP_PATHS_MANIFEST定数定義 |
| index.ts | `packages/next/src/build/index.ts` | ソース | ビルドプロセスでのマニフェスト読み込み・変換 |
| get-route-from-entrypoint.ts | `packages/next/src/server/get-route-from-entrypoint.ts` | ソース | エントリポイント名からルートパスへの変換 |
| manifest-loader.ts | `packages/next/src/shared/lib/turbopack/manifest-loader.ts` | ソース | Turbopack用のマニフェストローダー |
| base-server.ts | `packages/next/src/server/base-server.ts` | ソース | サーバーランタイムでのマニフェスト利用 |
