# 機能設計書 1-next dev

## 概要

本ドキュメントは、Next.jsの開発サーバー起動コマンド `next dev` の機能設計を記述する。開発者がローカル環境でアプリケーションを開発する際の中核となるCLIコマンドであり、ファイル変更検知・Hot Module Replacement（HMR）・エラーオーバーレイなどの開発体験を提供する。

### 本機能の処理概要

`next dev` コマンドは、Next.jsアプリケーションの開発サーバーを起動し、ファイル変更の検知とHMRによる即時反映を提供するCLIコマンドである。

**業務上の目的・背景**：Webアプリケーション開発において、コード変更を即座にブラウザに反映する仕組みは開発効率に直結する。`next dev` は開発者がソースコードを編集するたびにフルページリロードを行うことなく差分だけを反映するHMRを提供し、開発イテレーションを高速化する。また、コンパイルエラーやランタイムエラーをブラウザ上にオーバーレイ表示することで、素早いデバッグを可能にする。

**機能の利用シーン**：開発者がNext.jsアプリケーションのコードを編集・テスト・デバッグする際に使用する。プロジェクトのルートディレクトリで `next dev` を実行し、ブラウザからローカルサーバーにアクセスして開発を行う。

**主要な処理内容**：
1. プロジェクトディレクトリの検証とバンドラー（Turbopack/Webpack/Rspack）の選択
2. ポートの検証と予約ポートチェック
3. HTTPS自己署名証明書の生成（オプション）
4. 子プロセスとしての開発サーバーの起動（fork）
5. プリフライトチェック（依存パッケージの検証）
6. テレメトリの記録とセッション管理
7. シグナルハンドリング（SIGINT/SIGTERM）による安全なシャットダウン
8. サーバー再起動の自動ハンドリング（RESTART_EXIT_CODE）

**関連システム・外部連携**：Turbopack/Webpack/Rspackバンドラーとの統合、テレメトリサーバーへのデータ送信、トレースのアップロード（オプション）

**権限による制御**：特段の権限制御はないが、HTTPS証明書の生成やポートバインドにはOS権限が必要な場合がある。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 12 | 開発オーバーレイ (Dev Overlay) | 補助機能 | 開発サーバー実行時にのみ表示されるオーバーレイUI |
| 13 | DevToolsインジケーター | 補助機能 | 開発サーバー実行時にのみ表示 |
| 14 | DevToolsメニュー (Panel Selector) | 参照画面 | DevToolsメニューの表示 |
| 15 | ビルドエラー画面 | 補助機能 | 開発サーバーでのコンパイル結果を受けてエラー表示 |
| 16 | ランタイムエラー画面 | 補助機能 | 開発モード時のランタイムエラー検出と表示 |
| 19 | ユーザー設定パネル (Preferences) | 補助機能 | 開発サーバー設定のAPI呼び出しによるDevToolsインジケーター非表示化 |

## 機能種別

CLIコマンド / サーバー起動 / 開発環境管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| directory | string | No | プロジェクトディレクトリのパス。未指定時はカレントディレクトリ | 存在するディレクトリであること |
| --port, -p | number | No | サーバーのリッスンポート（デフォルト: 3000） | 正の整数であること。予約ポートでないこと |
| --hostname, -H | string | No | サーバーのリッスンホスト名 | なし |
| --turbo / --turbopack | boolean | No | Turbopackバンドラーを使用 | --webpackと排他 |
| --webpack | boolean | No | Webpackバンドラーを使用 | --turbo/--turbopackと排他 |
| --inspect | [host:]port | No | Node.jsデバッガーのアドレス指定 | 有効なホスト:ポート形式 |
| --experimental-https | boolean | No | HTTPS自己署名証明書による起動 | なし |
| --experimental-https-key | string | No | HTTPSキーファイルのパス | ファイルが存在すること |
| --experimental-https-cert | string | No | HTTPS証明書ファイルのパス | ファイルが存在すること |
| --experimental-https-ca | string | No | HTTPS CA証明書ファイルのパス | ファイルが存在すること |
| --experimental-upload-trace | string | No | トレースアップロード先URL | 有効なURL |
| --disable-source-maps | boolean | No | ソースマップを無効化 | なし |
| --experimental-cpu-prof | boolean | No | CPUプロファイリングを有効化 | なし |

### 入力データソース

- CLI引数（Commander.jsライブラリで解析）
- 環境変数（PORT、NEXT_PRIVATE_DEV_DIR、TURBOPACK、NEXT_DISABLE_MEM_OVERRIDE等）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| サーバーURL | string | 起動したサーバーのURL（stdout表示） |
| distDir | string | ビルド出力ディレクトリのパス（子プロセスからIPCで受信） |
| テレメトリデータ | object | セッション情報・利用統計の匿名データ |
| トレースデータ | object | デバッグ用のトレースデータ（オプション） |
| CPUプロファイル | file | CPUプロファイルデータ（.next/cpu-profiles/、オプション） |

### 出力先

- 標準出力（サーバーURL、ログメッセージ）
- .next/ ディレクトリ（ビルドアーティファクト）
- テレメトリサーバー（匿名使用統計）
- トレースアップロード先（オプション）

## 処理フロー

### 処理シーケンス

```
1. バンドラー選択（parseBundlerArgs）
   └─ --turbopack / --webpack / 環境変数に基づきTurbopack/Webpack/Rspackを決定（デフォルトはTurbopack）
2. プロジェクトディレクトリの解決（getProjectDir）
   └─ 引数またはNEXT_PRIVATE_DEV_DIRからディレクトリを決定
3. ディレクトリ存在確認
   └─ 存在しない場合はエラーメッセージを表示して終了
4. ポート検証
   └─ 予約済みポートの場合はエラーメッセージを表示して終了
5. HTTPS証明書処理（オプション）
   └─ --experimental-https指定時、証明書ファイルの読み込みまたは自己署名証明書の生成
6. 子プロセスとしてサーバー起動（fork）
   └─ start-server.tsを子プロセスとして起動
   └─ Node.jsオプション（max-old-space-size、source-maps、debug）を設定
   └─ IPCメッセージで起動完了を受信
7. プリフライトチェック（preflight）
   └─ sass/node-sassの重複インストール検出
   └─ @next/fontの非推奨パッケージ検出
8. セッション管理
   └─ シグナルハンドラ（SIGINT/SIGTERM）の登録
   └─ 子プロセスの終了コードに応じた再起動またはセッション停止
```

### フローチャート

```mermaid
flowchart TD
    A[next dev 実行] --> B[バンドラー選択]
    B --> C[プロジェクトディレクトリ解決]
    C --> D{ディレクトリ存在?}
    D -->|No| E[エラー終了]
    D -->|Yes| F{ポート検証}
    F -->|予約済み| G[エラー終了]
    F -->|OK| H{HTTPS有効?}
    H -->|Yes| I[証明書処理]
    H -->|No| J[子プロセス起動]
    I --> J
    J --> K[IPC待機]
    K --> L{nextServerReady?}
    L -->|Yes| M[プリフライトチェック]
    M --> N[サーバー稼働中]
    N --> O{終了シグナル?}
    O -->|SIGINT/SIGTERM| P[セッション停止処理]
    O -->|子プロセス終了| Q{再起動コード?}
    Q -->|RESTART_EXIT_CODE| J
    Q -->|その他| P
    P --> R[テレメトリ送信]
    R --> S[プロセス終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | デフォルトバンドラー | バンドラー未指定時はTurbopackがデフォルトとして使用される | バンドラーフラグ・環境変数いずれも未設定時 |
| BR-02 | バンドラー排他制御 | --turbopack と --webpack は同時指定不可 | 複数バンドラーフラグ指定時にエラー終了 |
| BR-03 | デフォルトポート | ポート未指定時は3000を使用 | --portオプション未指定かつPORT環境変数未設定時 |
| BR-04 | ポート自動リトライ | ポートがデフォルト値の場合のみ別ポートでのリトライを許可 | portSourceが'default'の場合 |
| BR-05 | メモリ制限自動設定 | max-old-space-sizeが未設定の場合、システムメモリの50%を自動設定 | NEXT_DISABLE_MEM_OVERRIDE未設定時 |
| BR-06 | 自動再起動 | 子プロセスがRESTART_EXIT_CODEで終了した場合、自動的にサーバーを再起動 | next.config変更時等 |
| BR-07 | macOSウォッチャー制限 | macOSではファイルウォッチャー数を20に制限（Node.jsバグ回避） | os.platform() === 'darwin'の場合 |

### 計算ロジック

- メモリ制限計算: `maxOldSpaceSize = Math.floor(totalMemInMB * 0.5)`（システムメモリの50%）
- デバッグポート計算: `address.port = address.port === 0 ? 0 : address.port + 1`（親プロセスと異なるポートを使用）

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

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

本機能はデータベースを直接操作しない。テレメトリデータはローカルのConfストレージ（JSONファイル）に保存される。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ディレクトリ不在 | 指定されたプロジェクトディレクトリが存在しない | 正しいパスを指定して再実行 |
| - | 予約ポート使用 | 予約済みポートを指定した場合 | 別のポートを指定して再実行 |
| - | 複数バンドラー指定 | --turbopackと--webpackを同時に指定 | いずれか一方のみを指定 |
| - | 依存パッケージ重複 | sassとnode-sassの両方がインストールされている | node-sassを削除 |
| SIGKILL | 子プロセスタイムアウト | 子プロセスがSIGINT/SIGTERM後にCHILD_EXIT_TIMEOUT_MS以内に終了しない | SIGKILLで強制終了 |

### リトライ仕様

- ポートリトライ: portSourceが'default'の場合、使用中ポートに対して別ポートでのリトライを試行
- サーバー再起動: RESTART_EXIT_CODE受信時に自動再起動（ポートは前回使用値を維持）

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

本機能にはデータベーストランザクションはない。

## パフォーマンス要件

- サーバー起動時間: できるだけ短い起動時間が求められる（Turbopackによる高速化）
- HMR反映時間: ファイル変更からブラウザ反映まで数百ミリ秒程度
- メモリ使用量: システムメモリの50%をデフォルト上限として設定

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

- HTTPS自己署名証明書は実験的機能であり、本番環境では使用しない
- `--experimental-upload-trace` オプションは機密データを含むため、信頼できるURLのみに使用する
- デバッグポートの公開はセキュリティリスクとなるため、開発環境でのみ使用する

## 備考

- `next dev` コマンドはNext.js CLIのデフォルトコマンドとして設定されている（`isDefault: true`）
- NEXT_PRIVATE_DEV_DIR環境変数によりプロジェクトディレクトリを上書き可能
- 子プロセスのexit timeout はNEXT_EXIT_TIMEOUT_MS環境変数で設定可能（デフォルト100ms）
- Rspackバンドラーはnext.config.jsを経由してのみ設定可能であり、CLIフラグでは直接指定できない

---

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

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

### 推奨読解順序

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

まず、コマンドのオプション型定義とバンドラー列挙型を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | next-dev.ts | `packages/next/src/cli/next-dev.ts` | NextDevOptions型定義（42-58行目）で受け取るオプションの全体像を把握 |
| 1-2 | bundler.ts | `packages/next/src/lib/bundler.ts` | Bundler列挙型（2-6行目）でバンドラーの種類を把握 |
| 1-3 | start-server.ts | `packages/next/src/server/lib/start-server.ts` | StartServerOptions型定義（115-126行目）でサーバー起動オプションの構造を把握 |

**読解のコツ**: TypeScriptの型定義から読み始めることで、関数間で受け渡されるデータの全体像をつかめる。`PortSource`型（60行目）は'cli'|'default'|'env'の3値であり、ポートリトライの判定に使われる。

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

CLIのエントリーポイントからnextDev関数の呼び出しまでの流れを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | next.ts | `packages/next/src/bin/next.ts` | devコマンドの登録（261-342行目）、Commanderによるオプション定義とアクション |
| 2-2 | next-dev.ts | `packages/next/src/cli/next-dev.ts` | nextDev関数（170-419行目）がメインのエントリーポイント |

**主要処理フロー**:
1. **261-342行目（next.ts）**: devコマンドの定義。`isDefault: true`でデフォルトコマンドに設定
2. **170-178行目（next-dev.ts）**: バンドラー選択とプロジェクトディレクトリの解決
3. **230-237行目**: ポート検証とリトライ許可の判定
4. **260-378行目**: startServer関数で子プロセスをforkしてサーバーを起動

#### Step 3: 子プロセス管理を理解する

開発サーバーの実際の起動は子プロセスで行われる。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | next-dev.ts | `packages/next/src/cli/next-dev.ts` | startServer関数（260-378行目）での子プロセスforkとIPCメッセージング |
| 3-2 | start-server.ts | `packages/next/src/server/lib/start-server.ts` | startServer関数（170行目以降）で実際のHTTPサーバーを起動 |

**主要処理フロー**:
- **303-329行目**: `fork(startServerPath, ...)`で子プロセスを生成。環境変数でTurbopack・CPUプロファイル・Node.jsオプションを渡す
- **331-350行目**: 子プロセスからのIPCメッセージ（nextWorkerReady / nextServerReady）を処理
- **352-377行目**: 子プロセスの終了イベントを処理。RESTART_EXIT_CODEなら再起動

#### Step 4: セッション管理を理解する

シグナルハンドリングとテレメトリ送信の流れを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | next-dev.ts | `packages/next/src/cli/next-dev.ts` | handleSessionStop関数（79-162行目）でのクリーンアップ処理 |
| 4-2 | storage.ts | `packages/next/src/telemetry/storage.ts` | Telemetryクラス（51行目以降）でのデータ保存と送信 |

**主要処理フロー**:
- **79-99行目**: 子プロセスへのシグナル転送とタイムアウト付き待機
- **104-138行目**: テレメトリセッション停止イベントの記録
- **144-152行目**: トレースデータのアップロード（オプション）
- **155-161行目**: CPUプロファイル保存とカーソル復元

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

```
bin/next.ts (CLIエントリーポイント)
    │
    ├─ cli/next-dev.ts::nextDev()
    │      ├─ lib/bundler.ts::parseBundlerArgs()
    │      ├─ lib/get-project-dir.ts::getProjectDir()
    │      ├─ lib/helpers/get-reserved-port.ts::isPortIsReserved()
    │      ├─ lib/mkcert.ts::createSelfSignedCertificate() [HTTPS時]
    │      ├─ startServer() [内部関数]
    │      │      ├─ fork(start-server.ts) [子プロセス]
    │      │      │      └─ server/lib/start-server.ts::startServer()
    │      │      │             └─ server/lib/router-server.ts::initialize()
    │      │      └─ IPCメッセージハンドリング
    │      ├─ preflight() [内部関数]
    │      │      └─ lib/get-package-version.ts::getPackageVersion()
    │      └─ handleSessionStop() [シグナルハンドラ]
    │             ├─ telemetry/events/session-stopped.ts
    │             ├─ telemetry/storage.ts::Telemetry
    │             └─ trace/upload-trace.ts::uploadTrace()
    │
    └─ シグナルハンドラ (SIGINT/SIGTERM/exit)
```

### データフロー図

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

CLI引数 ─────────────▶ next.ts (Commander解析) ──────▶ NextDevOptions
                              │
NextDevOptions ──────▶ nextDev() ──────────────────▶ startServer()
                              │                            │
環境変数 ────────────▶ parseBundlerArgs() ──────────▶ Bundler enum
                              │
                       fork(start-server.ts) ───────▶ 子プロセス
                              │                            │
                       IPCメッセージ ◀──────────────── {nextServerReady, port, distDir}
                              │
SIGINT/SIGTERM ──────▶ handleSessionStop() ─────────▶ テレメトリ送信
                                                      ▶ トレースアップロード
                                                      ▶ プロセス終了
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| next.ts | `packages/next/src/bin/next.ts` | ソース | CLIメインエントリーポイント。devコマンドの定義 |
| next-dev.ts | `packages/next/src/cli/next-dev.ts` | ソース | next devコマンドのメイン処理 |
| bundler.ts | `packages/next/src/lib/bundler.ts` | ソース | バンドラー選択ロジック |
| start-server.ts | `packages/next/src/server/lib/start-server.ts` | ソース | HTTPサーバーの起動処理 |
| router-server.ts | `packages/next/src/server/lib/router-server.ts` | ソース | リクエストルーティングの初期化 |
| get-project-dir.ts | `packages/next/src/lib/get-project-dir.ts` | ソース | プロジェクトディレクトリの解決 |
| get-reserved-port.ts | `packages/next/src/lib/helpers/get-reserved-port.ts` | ソース | 予約ポートチェック |
| mkcert.ts | `packages/next/src/lib/mkcert.ts` | ソース | 自己署名証明書の生成 |
| utils.ts | `packages/next/src/server/lib/utils.ts` | ソース | ユーティリティ関数（printAndExit等） |
| storage.ts | `packages/next/src/telemetry/storage.ts` | ソース | テレメトリデータの管理 |
| cpu-profile.ts | `packages/next/src/server/lib/cpu-profile.ts` | ソース | CPUプロファイリング機能 |
| upload-trace.ts | `packages/next/src/trace/upload-trace.ts` | ソース | トレースデータのアップロード |
| get-package-version.ts | `packages/next/src/lib/get-package-version.ts` | ソース | パッケージバージョン取得 |
| find-pages-dir.ts | `packages/next/src/lib/find-pages-dir.ts` | ソース | pages/appディレクトリの検出 |
