# 帳票設計書 10-server-reference-manifest

## 概要

本ドキュメントは、Next.jsビルドプロセスにおいて生成される `server-reference-manifest` の設計を記述する。このマニフェストは、サーバーアクション（Server Actions）の参照情報を管理し、クライアントからサーバーアクションを呼び出す際のモジュール解決・暗号化情報を提供する。

### 本帳票の処理概要

server-reference-manifest は、`FlightClientEntryPlugin` の `createActionAssets` メソッドによって生成されるファイルである。サーバーアクション（`'use server'` ディレクティブで定義された関数）のアクションID、モジュールID、ワーカー情報を収集し、サーバーがクライアントからのアクション呼び出しを正しいモジュールにルーティングできるようにする。JSONファイルとJavaScript（Edge用）の2形式で出力される。

**業務上の目的・背景**：React Server Actionsは、クライアントからサーバー側の関数を直接呼び出す仕組みを提供する。クライアントはアクションIDを送信し、サーバーはこのIDから対応するモジュールと関数を解決して実行する。本マニフェストは、このアクションID→モジュール解決の変換テーブルと、アクション呼び出しの暗号化に使用する暗号化キーを提供する。

**帳票の利用シーン**：クライアントからのServer Action呼び出し時のアクションIDからモジュール解決、Node.jsサーバーとEdgeサーバー双方でのアクション処理、アクション呼び出しの暗号化検証に使用される。

**主要な出力内容**：
1. `node` - Node.jsサーバー用のアクションマッピング（アクションID→ワーカー情報）
2. `edge` - Edgeサーバー用のアクションマッピング
3. `encryptionKey` - サーバーアクションの暗号化キー

**帳票の出力タイミング**：`next build` コマンド実行時のWebpackコンパイルプロセス中、FlightClientEntryPluginの `createActionAssets` メソッドが実行された際に出力される。

**帳票の利用者**：Next.jsサーバーランタイム（Server Action処理）、Edgeランタイム（Edge Server Action処理）、React Flightランタイム。

## 帳票種別

ビルドマニフェスト（JSON/JavaScript形式のサーバーアクション参照ファイル）

## 利用画面

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

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | JSON（`.json`）およびJavaScript（`.js`） |
| 用紙サイズ | N/A（データファイル） |
| 向き | N/A |
| ファイル名 | `server-reference-manifest.json` / `server-reference-manifest.js` |
| 出力方法 | `compilation.emitAsset` 経由（`.next/server/server-reference-manifest.{json,js}`） |
| 文字コード | UTF-8 |

### PDF固有設定

N/A

### Excel固有設定

N/A

## 帳票レイアウト

### レイアウト概要

2つの形式で出力される。

**JSON形式**（Node.jsサーバー用）:
```json
{
  "node": {
    "action-id-hash-1": {
      "workers": {
        "app/page": { "moduleId": "123", "async": false }
      },
      "layer": {
        "app/page": "actionBrowser"
      }
    }
  },
  "edge": { ... },
  "encryptionKey": "base64-encoded-key"
}
```

**JavaScript形式**（Edgeランタイム用）:
```javascript
self.__RSC_SERVER_MANIFEST = '{"node":{...},"edge":{...},"encryptionKey":"process.env.NEXT_SERVER_ACTIONS_ENCRYPTION_KEY"}'
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | encryptionKey（JSON版） | サーバーアクション暗号化キー | `this.encryptionKey` | 文字列 |
| 2 | encryptionKey（JS版） | 環境変数参照文字列 | 固定値 `'process.env.NEXT_SERVER_ACTIONS_ENCRYPTION_KEY'` | 文字列 |

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | node[actionId] | Node.jsサーバー用アクション定義 | `pluginState.serverActions[id]` | オブジェクト | N/A |
| 2 | edge[actionId] | Edgeサーバー用アクション定義 | `pluginState.edgeServerActions[id]` | オブジェクト | N/A |
| 3 | workers[entryName] | エントリごとのワーカーモジュール情報 | `pluginState.serverActionModules[name]` | `{ moduleId, async }` | N/A |
| 4 | layer[entryName] | アクションのレイヤー情報 | `action.layer[name]` | 文字列 | N/A |

### フッター部

N/A

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| サーバーアクション定義 | `'use server'` ディレクティブを持つ関数の存在 | Yes |
| アクションモジュール | `next-flight-action-entry-loader` を含むモジュールリクエスト | Yes |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| N/A | アクションID順 | pluginStateのキー順 |

### 改ページ条件

N/A

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

N/A

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

N/A

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| アクションID | サーバーアクション関数のハッシュ | N/A | FlightClientEntryPluginが収集 |
| ワーカーモジュール情報 | `pluginState.serverActionModules[name][client/server]` | N/A | actionBrowserレイヤーはclient、それ以外はserver |
| Edge版encryptionKey | 固定文字列 `'process.env.NEXT_SERVER_ACTIONS_ENCRYPTION_KEY'` | N/A | ランタイムで環境変数を参照 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[Webpackコンパイル] --> B[FlightClientEntryPlugin.apply]
    B --> C[createActionAssets呼び出し]
    C --> D[serverActions/edgeServerActions初期化]
    D --> E[モジュールグラフをtraverse]
    E --> F{flight-action-entry-loaderか?}
    F -->|Yes| G[serverActionModulesにマッピング記録]
    F -->|No| H[スキップ]
    G --> I[pluginState.serverActionsをイテレート]
    I --> J[各アクションのworkers情報を構築]
    J --> K[serverManifest構築 node/edge/encryptionKey]
    K --> L[server-reference-manifest.json出力]
    L --> M[server-reference-manifest.js出力 Edge用]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| アクションモジュール未解決 | serverActionModulesにエントリがない場合 | ランタイムエラーの可能性 | Server Action定義の確認 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | サーバーアクション数に依存（通常は数十件） |
| 目標出力時間 | Webpackコンパイル時間内 |
| 同時出力数上限 | 1（JSON + JS の2ファイル） |

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

server-reference-manifest.jsonの`encryptionKey`フィールドにはサーバーアクションの暗号化キーが含まれる。これは秘密情報であるため、`.next/server/` ディレクトリの外部非公開が必須。Edge版のJSファイルでは暗号化キーを直接埋め込まず、`process.env.NEXT_SERVER_ACTIONS_ENCRYPTION_KEY` 環境変数の参照文字列が設定される。

## 備考

- JSON形式とJavaScript形式の2ファイルが出力される
- JavaScript形式は `self.__RSC_SERVER_MANIFEST` にJSONの二重シリアライズ文字列がセットされる
- Edge版ではencryptionKeyが環境変数参照に置き換えられ、シークレットがJSバンドルに直接含まれないようにする
- `this.assetPrefix` がファイルパスのプレフィックスとして使用される
- `__client_imported__=true` クエリパラメータで、クライアントからインポートされたアクションかどうかを判別する
- `WEBPACK_LAYERS.actionBrowser` レイヤーの場合は 'client'、それ以外は 'server' としてワーカーモジュールを選択

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | flight-client-entry-plugin.ts | `packages/next/src/build/webpack/plugins/flight-client-entry-plugin.ts` | `ActionManifest`型（importで参照）。node/edge/encryptionKeyの構造 |
| 1-2 | constants.ts | `packages/next/src/shared/lib/constants.ts` | `SERVER_REFERENCE_MANIFEST`定数（128行目） |

**読解のコツ**: ActionManifest型は `{ node: Record<actionId, ActionEntry>, edge: Record<actionId, ActionEntry>, encryptionKey: string }` という構造。各ActionEntryにはworkers/layerが含まれる。

#### Step 2: アクション収集処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | flight-client-entry-plugin.ts | `packages/next/src/build/webpack/plugins/flight-client-entry-plugin.ts` | pluginState（104行目）のserverActions/edgeServerActions。ビルド中にサーバーアクション情報が蓄積される |

**主要処理フロー**:
1. **104行目**: `pluginState.serverActions` にサーバーアクション情報が蓄積
2. **1002行目**: Edgeサーバー時は `pluginState.edgeServerActions` を参照

#### Step 3: マニフェスト生成処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | flight-client-entry-plugin.ts | `packages/next/src/build/webpack/plugins/flight-client-entry-plugin.ts` | `createActionAssets`メソッド（1097〜1181行目） |

**主要処理フロー**:
- **1098〜1099行目**: serverActions/edgeServerActions初期化
- **1101〜1124行目**: モジュールグラフをtraverseしてserverActionModulesにマッピング
- **1126〜1152行目**: pluginState.serverActions/edgeServerActionsをイテレートしてworkers情報を構築
- **1154〜1162行目**: serverManifest/edgeServerManifest構築
- **1171〜1180行目**: emitAssetでJSON/JS出力

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

```
next build
    |
    +-- Webpack compilation
            |
            +-- FlightClientEntryPlugin.apply()
                    |
                    +-- createActionAssets() [1097行目]
                            |
                            +-- traverseModules() [1101行目]
                            |       |
                            |       +-- flight-action-entry-loader判定
                            |       +-- serverActionModulesへのマッピング
                            |
                            +-- pluginState.serverActions走査 [1126行目]
                            |
                            +-- serverManifest構築 [1154行目]
                            |
                            +-- compilation.emitAsset(server-reference-manifest.js) [1171行目]
                            |
                            +-- compilation.emitAsset(server-reference-manifest.json) [1177行目]
```

### データフロー図

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

pluginState.serverActions --------> createActionAssets()
pluginState.edgeServerActions ----->    |
pluginState.serverActionModules -->    +-- workers情報構築
this.encryptionKey --------------->    +-- serverManifest構築
                                        |
                                        +-- JSON.stringify ------> .next/server/server-reference-manifest.json
                                        +-- self.__RSC_SERVER ---> .next/server/server-reference-manifest.js
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| flight-client-entry-plugin.ts | `packages/next/src/build/webpack/plugins/flight-client-entry-plugin.ts` | ソース | FlightClientEntryPlugin実装（createActionAssets） |
| constants.ts | `packages/next/src/shared/lib/constants.ts` | ソース | SERVER_REFERENCE_MANIFEST定数 |
| middleware-plugin.ts | `packages/next/src/build/webpack/plugins/middleware-plugin.ts` | ソース | Edge Function定義時のserver-reference-manifest参照 |
| manifest-loader.ts | `packages/next/src/shared/lib/turbopack/manifest-loader.ts` | ソース | Turbopack用のマニフェストローダー |
| app-render.tsx | `packages/next/src/server/app-render/app-render.tsx` | ソース | SSR時のserver-reference-manifest利用 |
