# 機能設計書 68-Edge Runtime

## 概要

本ドキュメントは、Next.jsのEdge Runtime機能の設計について記述する。Edge RuntimeはCDNエッジ環境でサーバーサイドコードを実行するための軽量ランタイムであり、Web標準API（Fetch API、Web Streams等）に基づいたサンドボックス環境を提供する。

### 本機能の処理概要

Edge Runtimeは、ミドルウェアやEdge API Routes等のサーバーサイドコードをエッジ環境で実行するための仕組みであり、Node.jsランタイムとは異なる制約のある軽量なJavaScript実行環境を提供する。

**業務上の目的・背景**：CDNエッジでコードを実行することで、ユーザーにより近い場所でリクエストを処理し、レイテンシーを大幅に削減できる。Edge Runtimeは、Node.js APIに依存しないWeb標準ベースのランタイムを提供し、エッジデプロイメントを可能にする。

**機能の利用シーン**：ミドルウェア（middleware.ts）の実行、`runtime: 'edge'`を指定したAPI Routesの実行、Edge SSRの実行に使用される。

**主要な処理内容**：
1. Edge Runtimeサンドボックスの構築（モジュールコンテキスト管理）
2. NextRequestHint/NextFetchEvent等のWeb標準互換オブジェクトの生成
3. ミドルウェアハンドラの実行とリクエスト/レスポンス変換
4. Edge Route Module Wrapper によるApp Router Route Handlerの実行
5. 開発時のエラースタックトレース付与（edge-serverタグ）
6. WASMモジュール・環境変数・インラインアセットのサンドボックスへの注入

**関連システム・外部連携**：edge-runtime（npm パッケージ）、Web Crypto API、Fetch API、Web Streams API。

**権限による制御**：Edge RuntimeではNode.js APIの一部（fs、net、child_process等）が使用不可。EDGE_UNSUPPORTED_NODE_APISで定義される。

## 関連画面

Edge Runtimeは画面に紐づくものではなく、サーバーサイドのリクエスト処理基盤として機能する。

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | ミドルウェア/Edge API Route | 実行環境 | エッジ環境でのサーバーサイドコード実行 |

## 機能種別

ランタイム / サンドボックス / リクエスト処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| name | string | Yes | モジュール名（サンドボックス識別用） | - |
| paths | string[] | Yes | 実行するモジュールのファイルパス | 有効なファイルパス |
| request | NodejsRequestData | Yes | リクエストデータ | - |
| edgeFunctionEntry | EdgeFunctionDefinition | Yes | エッジ関数定義（assets、wasm、env） | - |
| useCache | boolean | Yes | モジュールコンテキストのキャッシュ使用フラグ | - |
| distDir | string | Yes | ビルド出力ディレクトリ | - |

### 入力データソース

- HTTPリクエスト（Node.jsのIncomingMessage経由）
- ビルド時に生成されたエッジ関数バンドル
- ミドルウェアマニフェスト

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| FetchEventResult | object | レスポンスデータ（response、waitUntil Promise、fetchMetrics） |

### 出力先

FetchEventResultとしてRouter Serverに返却され、最終的にHTTPレスポンスとしてクライアントに送信される。

## 処理フロー

### 処理シーケンス

```
1. サンドボックス環境の構築（getModuleContext）
   └─ EdgeRuntimeインスタンスの生成
   └─ WASM/環境変数/アセットの注入
2. リクエストオブジェクトの変換
   └─ NodejsRequestData → NextRequestHint（Web標準互換）
3. アダプター実行（adapter関数）
   └─ NextFetchEventの生成
   └─ ハンドラの呼び出し（ミドルウェア/Route Handler）
   └─ レスポンスの収集
4. レスポンスの変換
   └─ Web Response → FetchEventResult
5. エラー処理（開発モード）
   └─ edge-serverタグ付きエラースタックトレース生成
```

### フローチャート

```mermaid
flowchart TD
    A[Edge関数実行要求] --> B{モジュールコンテキストキャッシュ?}
    B -->|あり| C[キャッシュからコンテキスト取得]
    B -->|なし| D[新規サンドボックス構築]
    D --> E[EdgeRuntime初期化]
    E --> F[WASM/env/assets注入]
    F --> C
    C --> G[NodejsRequestData → NextRequestHint変換]
    G --> H[adapter関数実行]
    H --> I[ハンドラ呼び出し]
    I --> J[FetchEventResult生成]
    J --> K{開発モード?}
    K -->|Yes| L[エラースタックトレースにedge-serverタグ付与]
    K -->|No| M[結果返却]
    L --> M
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-68-01 | モジュールコンテキストキャッシュ | useCache=trueの場合、モジュールコンテキストをMapでキャッシュし再利用する | useCache指定時 |
| BR-68-02 | Node.js API制限 | EDGE_UNSUPPORTED_NODE_APISで定義されたAPIは使用不可 | Edge Runtime内 |
| BR-68-03 | エラータグ付与 | 開発モードではエラーに'edge-server'タグを付与し、Dev Overlayでの表示を支援する | process.env.NODE_ENV === 'development' |
| BR-68-04 | FORBIDDEN_HEADERS | content-length、content-encoding、transfer-encodingヘッダーはレスポンスから除去される | Edge関数レスポンス処理時 |
| BR-68-05 | PageSignatureError | requestプロパティ・respondWith・waitUntilメソッドへのアクセスはPageSignatureErrorをthrowする | NextRequestHintでの不正アクセス時 |

### 計算ロジック

特になし。

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

本機能は直接的なデータベース操作を行わない。Edge関数内でのfetch API経由のデータアクセスはサポートされる。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| PageSignatureError | ランタイムエラー | NextRequestHintの不正なプロパティアクセス時 | エラーメッセージにページ名を含めて開発者に通知 |
| SandboxError | ランタイムエラー | サンドボックス内でのエラー発生時 | ErrorSourceシンボルでタグ付けしDev Overlayに表示 |
| ModuleLoadError | 初期化エラー | モジュールの読み込みに失敗した場合 | エラーログ出力 |

### リトライ仕様

該当なし。

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

該当なし。

## パフォーマンス要件

- モジュールコンテキストのキャッシュにより、同一モジュールの繰り返し実行時のオーバーヘッドを削減する
- Edge Runtimeは軽量であり、Node.jsランタイムと比較してコールドスタートが高速
- clearAllModuleContexts()でメモリリークを防止

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

- サンドボックス環境により、Edge関数からNode.jsのファイルシステム等へのアクセスを制限する
- 環境変数はedgeFunctionEntry.envで明示的に注入されたもののみアクセス可能
- WASM実行はサンドボックス内に制限される

## 備考

- Edge Runtimeは`next/dist/compiled/edge-runtime`パッケージを基盤としている
- clearModuleContext()はHMR時のモジュール更新で使用される
- intervalsManager/timeoutsManagerでタイマーリソースを管理し、メモリリークを防止する

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | types.ts | `packages/next/src/server/web/types.ts` | RequestData、FetchEventResult、NodejsRequestData等の型定義 |
| 1-2 | error.ts | `packages/next/src/server/web/error.ts` | PageSignatureError等のエラー型 |

#### Step 2: サンドボックス環境を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | context.ts | `packages/next/src/server/web/sandbox/context.ts` | getModuleContext()関数。EdgeRuntimeインスタンスの構築とキャッシュ管理 |
| 2-2 | sandbox.ts | `packages/next/src/server/web/sandbox/sandbox.ts` | withTaggedErrors()デコレータとgetRuntimeContext()関数 |

**主要処理フロー**:
- **context.ts 56行目**: moduleContextsマップでキャッシュ管理
- **context.ts 63-68行目**: clearAllModuleContexts()でリソースクリーンアップ
- **context.ts 78-80行目**: clearModuleContext()でHMR時の個別クリーンアップ
- **sandbox.ts 48-69行目**: withTaggedErrors()で開発モード時のエラーに'edge-server'タグ付与
- **sandbox.ts 71-80行目**: getRuntimeContext()でモジュールコンテキスト取得

#### Step 3: アダプター層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | adapter.ts | `packages/next/src/server/web/adapter.ts` | adapter()関数とNextRequestHintクラス。Node.jsリクエストからWeb標準リクエストへの変換 |

**主要処理フロー**:
- **40-64行目**: NextRequestHintクラス。request/respondWith/waitUntilへのアクセスでPageSignatureErrorをthrow
- **71-78行目**: AdapterOptions型定義

#### Step 4: Edge Route Module Wrapperを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | edge-route-module-wrapper.ts | `packages/next/src/server/web/edge-route-module-wrapper.ts` | EdgeRouteModuleWrapperクラス。App Router Route HandlerのEdge Runtime実行ラッパー |

**主要処理フロー**:
- **28-40行目**: EdgeRouteModuleWrapperクラス。privateコンストラクタでルートモジュールを保持
- **51-68行目**: wrap()静的メソッド。adapter()を通じてEdge Route Handlerを実行

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

```
Edge Function実行要求
    │
    ├─ sandbox.ts: getRuntimeContext() / withTaggedErrors()
    │      └─ context.ts: getModuleContext()
    │             ├─ EdgeRuntime [edge-runtime パッケージ]
    │             ├─ WASM/env/assets注入
    │             └─ moduleContextsキャッシュ
    │
    ├─ adapter.ts: adapter()
    │      ├─ NextRequestHint構築
    │      ├─ NextFetchEvent構築
    │      ├─ ハンドラ呼び出し
    │      └─ FetchEventResult構築
    │
    └─ edge-route-module-wrapper.ts: EdgeRouteModuleWrapper.wrap()
           └─ adapter() → handler() → Response
```

### データフロー図

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

NodejsRequestData        ──▶  adapter()                      FetchEventResult
  url, method, headers          │                               response: Response
  body                          ├─ NextRequestHint構築           waitUntil: Promise
                                ├─ NextFetchEvent構築            fetchMetrics
                                ├─ ハンドラ実行
                                └─ レスポンス収集          ──▶  Router Serverへ返却

EdgeFunctionDefinition   ──▶  getModuleContext()
  assets, wasm, env             └─ EdgeRuntime構築
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| adapter.ts | `packages/next/src/server/web/adapter.ts` | ソース | Edge RuntimeアダプターとNextRequestHint |
| sandbox.ts | `packages/next/src/server/web/sandbox/sandbox.ts` | ソース | サンドボックス実行とエラータグ付与 |
| context.ts | `packages/next/src/server/web/sandbox/context.ts` | ソース | モジュールコンテキスト管理とEdgeRuntime構築 |
| edge-route-module-wrapper.ts | `packages/next/src/server/web/edge-route-module-wrapper.ts` | ソース | Edge Route Handlerラッパー |
| types.ts | `packages/next/src/server/web/types.ts` | ソース | 型定義 |
| error.ts | `packages/next/src/server/web/error.ts` | ソース | エラー型定義 |
| resource-managers.ts | `packages/next/src/server/web/sandbox/resource-managers.ts` | ソース | タイマーリソース管理 |
| fetch-inline-assets.ts | `packages/next/src/server/web/sandbox/fetch-inline-assets.ts` | ソース | インラインアセットのfetch処理 |
| globals.ts | `packages/next/src/server/web/globals.ts` | ソース | Edge Runtimeグローバル設定 |
