# 画面設計書 3-アプリケーションラッパー (_app)

## 概要

Pages Routerにおける全ページを包む共通コンポーネントの設計書。ページ間の状態保持、グローバルスタイルの注入、カスタムエラーハンドリングに使用される。

### 本画面の処理概要

**業務上の目的・背景**：Next.jsのPages Routerでは、ページ遷移のたびにページコンポーネントがアンマウント・再マウントされる。本コンポーネント（`_app`）は全てのページコンポーネントを包むラッパーとして機能し、ページ遷移間での状態保持やグローバルなレイアウト・スタイルの適用を可能にする。また、`getInitialProps`を通じた初期データ取得のハブとしても機能する。ユーザーはこのコンポーネントを拡張してカスタムAppを作成し、全ページに共通する処理（認証チェック、テーマプロバイダ、グローバルCSS等）を注入できる。

**画面へのアクセス方法**：本コンポーネントは直接アクセスする画面ではなく、Pages Router配下の全ページリクエスト時にNext.jsランタイムが自動的にページコンポーネントをラップする形で呼び出される。

**主要な操作・処理内容**：
1. `getInitialProps`でAppContextからComponentとctxを取得し、ページコンポーネントの`getInitialProps`を呼び出してpagePropsを取得する
2. `render`メソッドでpropsからComponentとpagePropsを取り出し、`<Component {...pageProps} />`としてページコンポーネントをレンダリングする
3. `loadGetInitialProps`ユーティリティを使用して、ページコンポーネントのgetInitialPropsを安全に呼び出す

**画面遷移**：
- 遷移元：本コンポーネントはPages Router配下の全ページの親として機能する。`_document`からHTML構造が提供され、その中で本コンポーネントがレンダリングされる
- 遷移先：props.Componentとして渡されるページコンポーネントをレンダリングする。エラー発生時は`_error`コンポーネントが表示される

**権限による表示制御**：デフォルトの実装では権限による表示制御は行わない。ユーザーがカスタムAppでミドルウェア的な認証チェックを追加することは可能。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 31 | カスタムApp | 主機能 | 全ページを包む共通コンポーネントとしてのページ初期化・状態保持処理 |
| 26 | Pages Router | 補助機能 | Pages Routerを通じたページコンポーネントの受け渡しとレンダリング |
| 34 | サーバーサイドレンダリング（SSR） | 補助機能 | getInitialPropsによる初期データ取得 |

## 画面種別

ラッパー（共通レイアウト）

## URL/ルーティング

特定のURLパターンは持たない。Pages Router配下の全ページリクエストで自動的に適用される。

## 入出力項目

| 項目名 | 入出力 | 型 | 必須 | 説明 |
|--------|--------|------|------|------|
| Component | 入力 | NextComponentType | はい | 現在表示するページコンポーネント |
| pageProps | 入力 | any | はい | ページコンポーネントのgetInitialPropsで取得されたプロパティ |
| router | 入力 | Router | はい | Next.jsルーターインスタンス |
| レンダリング結果 | 出力 | ReactElement | はい | ページコンポーネントのレンダリング結果 |

## 表示項目

| 項目名 | 表示位置 | 説明 |
|--------|----------|------|
| ページコンポーネント | コンポーネント全体 | props.Componentとして渡されたページコンポーネントをpagePropsと共にレンダリング |

## イベント仕様

### 1-getInitialProps

ページ遷移時（サーバーサイドレンダリング時またはクライアントサイドナビゲーション時）に`appGetInitialProps`が呼ばれ、`loadGetInitialProps`を通じてページコンポーネントの`getInitialProps`を実行し、結果を`{ pageProps }`として返す。

## データベース更新仕様

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| なし | - | - | 本画面はデータベースへのアクセスを行わない |

### テーブル別更新項目詳細

データベース操作なし。

## メッセージ仕様

| メッセージID | 種別 | 条件 | メッセージ内容 |
|-------------|------|------|----------------|
| ERR-INSTANCE-METHOD | エラー | getInitialPropsがインスタンスメソッドとして定義された場合 | "{name}.getInitialProps()" is defined as an instance method |
| ERR-NO-PROPS | エラー | getInitialPropsがnull/undefinedを返した場合 | "{name}.getInitialProps()" should resolve to an object. But found "{props}" instead. |
| WARN-EMPTY-PROPS | 警告 | 開発環境でgetInitialPropsが空オブジェクトを返した場合 | {name} returned an empty object from `getInitialProps`. This de-optimizes and prevents automatic static optimization. |

## 例外処理

| 例外条件 | 挙動 |
|----------|------|
| ページコンポーネントにgetInitialPropsがない場合 | 空オブジェクト`{}`をpagePropsとして返す |
| getInitialPropsがインスタンスメソッドの場合（開発環境） | エラーをスローして開発者に通知 |
| getInitialPropsがnull/undefinedを返した場合 | エラーをスロー |
| レスポンスが既に送信済みの場合 | propsの検証をスキップしてそのまま返す |

## 備考

- React.Componentクラスを継承したクラスコンポーネントとして実装されている
- `origGetInitialProps`に元のgetInitialProps関数が保持されており、ユーザーがオーバーライドした場合でも元の実装にアクセス可能
- ジェネリクス`<P, CP, S>`によりプロパティ・ページプロパティ・状態の型パラメータ化に対応
- `AppType`、`AppProps`、`AppContext`、`AppInitialProps`、`NextWebVitalsMetric`の型がエクスポートされ、ユーザーのカスタムApp実装で利用可能
- `NextWebVitalsMetric`はWeb Vitals（CLS, FCP, FID, INP, LCP, TTFB）とNext.js独自メトリクスの型を定義
- `loadGetInitialProps`はgetInitialPropsの呼び出しを安全にラップし、開発環境での警告とエラー検出を行う

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | utils.ts | `packages/next/src/shared/lib/utils.ts` | L163-168: `AppContextType`型 - Component, AppTree, ctx, routerフィールド |
| 1-2 | utils.ts | `packages/next/src/shared/lib/utils.ts` | L170-182: `AppInitialProps`, `AppPropsType`型 - pageProps, Component, router |
| 1-3 | _app.tsx | `packages/next/src/pages/_app.tsx` | L14-20: エクスポートされる型定義（AppContext, AppProps等） |

**読解のコツ**: `AppContextType`はジェネリクスでRouterの型を受け取る。`AppPropsType`は`AppInitialProps`を拡張し、`Component`と`router`に加え、SSG/SSPフラグを持つ。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | _app.tsx | `packages/next/src/pages/_app.tsx` | L26-32: `appGetInitialProps`関数 - loadGetInitialPropsでページのpropsを取得 |
| 2-2 | _app.tsx | `packages/next/src/pages/_app.tsx` | L34-46: `App`クラス - renderメソッドでComponentをレンダリング |

**主要処理フロー**:
1. **L30**: `loadGetInitialProps(Component, ctx)` - ページコンポーネントのgetInitialPropsを呼び出し
2. **L31**: `{ pageProps }` - 結果をpagePropsとしてラップして返却
3. **L42**: `this.props`からComponentとpagePropsを分割代入
4. **L44**: `<Component {...pageProps} />` - ページコンポーネントをレンダリング

#### Step 3: loadGetInitialPropsユーティリティを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | utils.ts | `packages/next/src/shared/lib/utils.ts` | L361-411: `loadGetInitialProps`関数 - getInitialPropsの安全な呼び出し |

**主要処理フロー**:
- **L367-373**: インスタンスメソッドとしてのgetInitialProps定義を検出してエラー
- **L377-385**: getInitialPropsがない場合のフォールバック処理
- **L387**: getInitialPropsの呼び出しとawait
- **L393-398**: 戻り値がnull/undefinedの場合のエラー
- **L400-408**: 空オブジェクトの場合の警告（開発環境）

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

```
Next.js Router (ページ遷移)
    |
    +-- App.getInitialProps(appContext)
    |       |
    |       +-- appGetInitialProps({ Component, ctx })
    |               |
    |               +-- loadGetInitialProps(Component, ctx)
    |                       |
    |                       +-- Component.getInitialProps(ctx)
    |
    +-- App.render()
            |
            +-- <Component {...pageProps} />
```

### データフロー図

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

AppContext -----------> appGetInitialProps() ---------> AppInitialProps
 (Component, ctx)       |                               ({ pageProps })
                        +-- loadGetInitialProps()
                            |
                            +-- Component.getInitialProps(ctx)
                                                            |
                                                            v
AppProps -------------> App.render() -----------------> ReactElement
 (Component,            |                               (<Component
  pageProps,            +-- Component展開                   {...pageProps}/>)
  router)               +-- pagePropsスプレッド
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| _app.tsx | `packages/next/src/pages/_app.tsx` | ソース | Appコンポーネント本体 |
| utils.ts | `packages/next/src/shared/lib/utils.ts` | ソース | loadGetInitialProps関数、型定義（AppContextType, AppInitialProps等） |
| router.ts | `packages/next/src/client/router.ts` | ソース | Routerクラス（AppPropsTypeのRouter型パラメータ） |
