# 機能設計書 14-レイアウト（Layouts）

## 概要

本ドキュメントは、Next.js App Routerにおけるレイアウト機能の設計を記述する。レイアウトはルート間で共有されるUIであり、ネストされたレイアウトにより階層的なUI構造を実現する。layout.tsxファイルによって定義される。

### 本機能の処理概要

レイアウト機能は、App Routerにおいてルートセグメント間で共有されるUIの定義と管理を行う機能である。

**業務上の目的・背景**：Webアプリケーションでは、ナビゲーションバー、サイドバー、フッター等の共通UIを複数のページ間で共有する必要がある。従来は各ページで共通コンポーネントを個別にインポートする必要があったが、レイアウト機能により、ファイルシステムの階層構造に基づいて自動的にUIの共有と再利用が実現される。

**機能の利用シーン**：アプリケーション全体のヘッダー・フッター定義、特定セクション（ダッシュボード、管理画面等）の共通レイアウト定義、認証済みエリアのラッパーコンポーネント定義などで利用される。

**主要な処理内容**：
1. `layout.tsx` ファイルの検出とLoaderTreeへの組み込み
2. ルートレイアウト（最上位のlayout.tsx）のhtml/body構造提供
3. ネストされたレイアウトの階層的レンダリング
4. レイアウトコンポーネントのServer Component/Client Component判定
5. ナビゲーション時のレイアウト状態保持（再レンダリング回避）

**関連システム・外部連携**：React Server Components、Suspenseバウンダリ、テンプレート機能。

**権限による制御**：レイアウト内で認証状態をチェックし、アクセス制御を実装可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 10 | デフォルトレイアウト (Default Layout) | 主機能 | ユーザー未定義時のデフォルトhtml/body構造の提供 |
| 18 | セグメントエクスプローラー (Route Info) | 補助機能 | 各セグメントのlayout・page・error・loading等のファイルツリー表示 |

## 機能種別

UI構造定義 / レンダリング制御

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| children | ReactNode | Yes | 子ルートのコンテンツ（page.tsxまたは子レイアウト） | - |
| params | Promise<Params> | No | 動的ルートパラメータ | - |

### 入力データソース

- ファイルシステム（`app/**/layout.tsx`）
- LoaderTree（ビルド時に生成されるルートツリー構造）
- ルートセグメントのモジュール情報

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| レイアウトUI | ReactNode | レイアウトコンポーネントのレンダリング結果 |
| CacheNodeSeedData | CacheNodeSeedData | レイアウトのキャッシュノードデータ |
| CSS/JSアセット | ReactNode | レイアウトに関連するスタイルシート・スクリプト |

### 出力先

- サーバーサイド: HTMLストリームの一部として出力
- クライアントサイド: DOMの更新

## 処理フロー

### 処理シーケンス

```
1. LoaderTreeからレイアウトモジュールの取得
   └─ parseLoaderTreeでmodulesからlayoutモジュールを抽出
2. レイアウトコンポーネントの解決
   └─ getLayoutOrPageModuleでモジュールをインポート
3. ルートレイアウト判定
   └─ rootLayoutIncludedフラグで最上位レイアウトかを判定
4. CSS/JSアセットの解決
   └─ createComponentStylesAndScriptsでスタイル・スクリプトを収集
5. 子コンポーネントの構築
   └─ parallelRoutesの再帰的処理でchildrenを生成
6. レイアウトコンポーネントのレンダリング
   └─ Server/Client Componentに応じたレンダリング
7. テンプレートのラップ
   └─ template.tsx存在時はテンプレートでラップ
```

### フローチャート

```mermaid
flowchart TD
    A[LoaderTree解析] --> B{layout.tsx存在?}
    B -->|Yes| C[レイアウトモジュール取得]
    B -->|No| D[children直接表示]
    C --> E{ルートレイアウト?}
    E -->|Yes| F[html/body構造提供]
    E -->|No| G[ネストレイアウト]
    F --> H[CSS/JSアセット解決]
    G --> H
    H --> I[parallelRoutes処理]
    I --> J[children生成]
    J --> K[レイアウトコンポーネントレンダリング]
    K --> L{template.tsx存在?}
    L -->|Yes| M[テンプレートラップ]
    L -->|No| N[最終出力]
    M --> N
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | ルートレイアウト必須 | 最上位のlayout.tsxはhtml/bodyタグを含む必要がある | ルートレイアウト |
| BR-02 | ネスト継承 | 親レイアウトは子ルートのすべてのページに自動適用 | 常時 |
| BR-03 | 状態保持 | ナビゲーション時にレイアウトは再レンダリングされない | ソフトナビゲーション時 |
| BR-04 | デフォルトexport必須 | layout.tsxはReactコンポーネントをデフォルトエクスポートする必要がある | 常時 |
| BR-05 | デフォルトレイアウト | ユーザーがルートレイアウトを定義しない場合、Next.jsがデフォルトのhtml/body構造を提供 | layout.tsx未定義時 |

### 計算ロジック

該当なし。

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | デフォルトexport不在 | layout.tsxにデフォルトexportがない | errorMissingDefaultExport関数でエラー |
| - | レンダリングエラー | レイアウトコンポーネント内のエラー | 親のerror.tsxバウンダリでキャッチ |

### リトライ仕様

該当なし。

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

該当なし。

## パフォーマンス要件

- レイアウトはナビゲーション間で再レンダリングされないため、状態とサーバーリソースが保持される
- Server Componentとして実装された場合、レイアウトのコードはクライアントバンドルに含まれない

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

- レイアウト内でのデータフェッチはServer Componentとして安全に実行可能
- レイアウトレベルでの認証チェック実装が推奨

## 備考

- `template.tsx` はレイアウトと類似するが、ナビゲーション時に新しいインスタンスが生成される点が異なる
- レイアウトからは子のpage.tsxに直接propsを渡すことはできない

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | app-dir-module.ts | `packages/next/src/server/lib/app-dir-module.ts` | LoaderTree型でlayoutモジュールの位置づけを理解 |
| 1-2 | parse-loader-tree.ts | `packages/next/src/shared/lib/router/utils/parse-loader-tree.ts` | parseLoaderTreeでmodulesからlayoutを抽出する仕組み |

**読解のコツ**: LoaderTreeは `[segment, parallelRoutes, modules]` の3要素タプルで、modulesオブジェクトのlayoutプロパティがレイアウトモジュールを指す。

#### Step 2: サーバーサイドのレイアウト処理

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | create-component-tree.tsx | `packages/next/src/server/app-render/create-component-tree.tsx` | createComponentTreeInternal関数（83行目以降）でレイアウトの処理フローを理解 |

**主要処理フロー**:
1. **136-137行目**: parseLoaderTreeでレイアウト情報を含むmodules取得
2. **139-147行目**: modulesからlayout/template/error/loading等の抽出
3. **194-206行目**: getLayoutOrPageModuleでレイアウトモジュール取得
4. **211-216行目**: rootLayoutAtThisLevel判定
5. **71-78行目**: errorMissingDefaultExportでデフォルトexport不在時のエラー

#### Step 3: クライアントサイドのレイアウトルーター

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | layout-router.tsx | `packages/next/src/client/components/layout-router.tsx` | OuterLayoutRouter（492行目）でクライアントサイドのレイアウトネスト管理 |
| 3-2 | layout-router.tsx | `packages/next/src/client/components/layout-router.tsx` | LayoutRouterContext.Provider（370-397行目）でレイアウトコンテキスト提供 |

**主要処理フロー**:
- **370-397行目**: LayoutRouterContext.Providerで子セグメントにコンテキスト提供
- **492行目**: OuterLayoutRouterがレイアウトの外枠を管理

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

```
createComponentTreeInternal (create-component-tree.tsx)
    |
    +-- parseLoaderTree
    |      └─ modules.layout の抽出
    |
    +-- getLayoutOrPageModule
    |      └─ レイアウトモジュールのインポート
    |
    +-- createComponentStylesAndScripts (template/error/loading)
    |
    +-- [再帰] createComponentTreeInternal (parallelRoutes)
    |
    +-- Layout Component レンダリング
           |
           +-- LayoutRouter (クライアントサイド)
                  |
                  +-- OuterLayoutRouter
                         +-- LoadingBoundary
                         +-- ErrorBoundary
                         +-- children (page/子レイアウト)
```

### データフロー図

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

layout.tsx -----------> parseLoaderTree --------+
                                                |
children (page) -----> createComponentTree -----+---> CacheNodeSeedData
                                                |
CSS/JS ------------- > getLayerAssets ----------+---> HTML/RSCペイロード
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| create-component-tree.tsx | `packages/next/src/server/app-render/create-component-tree.tsx` | ソース | サーバーサイドのレイアウト組み込み |
| layout-router.tsx | `packages/next/src/client/components/layout-router.tsx` | ソース | クライアントサイドのレイアウトルーター |
| app-router-context.shared-runtime.ts | `packages/next/src/shared/lib/app-router-context.shared-runtime.ts` | ソース | LayoutRouterContext定義 |
| parse-loader-tree.ts | `packages/next/src/shared/lib/router/utils/parse-loader-tree.ts` | ソース | LoaderTree解析 |
| app-dir-module.ts | `packages/next/src/server/lib/app-dir-module.ts` | ソース | LoaderTree型・モジュール取得 |
| interop-default.ts | `packages/next/src/server/app-render/interop-default.ts` | ソース | デフォルトexportの互換処理 |
