# 機能設計書 11-createSSRApp()

## 概要

本ドキュメントは、Vue 3のサーバーサイドレンダリング（SSR）対応アプリケーションインスタンスを生成するAPI `createSSRApp()` の機能設計書である。

### 本機能の処理概要

`createSSRApp()` は、サーバーサイドレンダリングされたHTMLを再利用（ハイドレーション）する前提でVueアプリケーションインスタンスを生成する関数である。通常の `createApp()` とほぼ同じインターフェースを持つが、マウント時にハイドレーションモードで動作する点が異なる。

**業務上の目的・背景**：Webアプリケーションの初期表示速度とSEO対策のため、サーバー側でHTMLを事前レンダリングし、クライアント側でインタラクティビティを付与する（ハイドレーション）パターンが求められる。`createSSRApp()` はこの一連の処理においてクライアント側のエントリーポイントとなる。

**機能の利用シーン**：SSR対応のVueアプリケーション（Nuxt.js等のフレームワーク利用時や独自SSR構成時）において、クライアント側のエントリーファイル（`entry-client.ts`）でサーバーレンダリング済みHTMLにVueアプリケーションをマウントする際に使用される。

**主要な処理内容**：
1. ハイドレーション対応レンダラー（HydrationRenderer）の初期化を保証する
2. Vueアプリケーションインスタンスの生成（`createAppAPI` 経由）
3. 開発モード時のネイティブタグチェックとコンパイラオプションチェックの注入
4. `mount` メソッドのオーバーライド（ハイドレーションモードでのマウントを強制）
5. コンテナ要素の正規化（セレクター文字列からDOM要素への解決）

**関連システム・外部連携**：`@vue/server-renderer` パッケージによるサーバー側レンダリング結果と連携する。`@vue/runtime-core` の `createHydrationRenderer` を通じてハイドレーション機構と統合される。

**権限による制御**：権限による制御は存在しない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 該当なし | - | createSSRApp()は直接的な画面関連はなく、SSRアプリケーション全体のインスタンス生成に使用 |

## 機能種別

アプリケーション初期化 / ハイドレーション制御

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| rootComponent | Component | Yes | ルートコンポーネント定義（オブジェクトまたは関数） | 関数でない場合はオブジェクトのコピーが作成される |
| rootProps | Data \| null | No | ルートコンポーネントに渡すProps | オブジェクトでない場合は警告を出しnullにリセット |

### 入力データソース

開発者がアプリケーションのエントリーポイントで直接呼び出す。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| app | App\<Element\> | Vueアプリケーションインスタンス（mount, unmount, use, component, directive, provide等のメソッドを持つ） |

### 出力先

呼び出し元に返却される。開発者はこの返却値に対して `app.mount('#app')` 等の操作を行う。

## 処理フロー

### 処理シーケンス

```
1. ensureHydrationRenderer() の呼び出し
   └─ ハイドレーション対応レンダラーが未初期化の場合のみ createHydrationRenderer() で生成
2. renderer.createApp() の呼び出し（createAppAPI経由）
   └─ AppContext の生成、アプリケーションオブジェクトの構築
3. 開発モード時の検証ロジック注入
   ├─ injectNativeTagCheck(): HTML/SVG/MathMLタグの名前検証
   └─ injectCompilerOptionsCheck(): ランタイムオンリービルドでのコンパイラオプション警告
4. mount メソッドのオーバーライド
   └─ normalizeContainer() でコンテナ要素を解決後、isHydrate=true でマウント
5. アプリケーションインスタンスの返却
```

### フローチャート

```mermaid
flowchart TD
    A[createSSRApp呼び出し] --> B[ensureHydrationRenderer]
    B --> C{ハイドレーションレンダラー初期化済み?}
    C -->|Yes| D[既存レンダラーを使用]
    C -->|No| E[createHydrationRenderer生成]
    E --> D
    D --> F[renderer.createApp でAppインスタンス生成]
    F --> G{__DEV__モード?}
    G -->|Yes| H[injectNativeTagCheck]
    H --> I[injectCompilerOptionsCheck]
    I --> J[mountメソッドをオーバーライド]
    G -->|No| J
    J --> K[Appインスタンスを返却]
    K --> L[app.mount呼び出し時]
    L --> M[normalizeContainer]
    M --> N{コンテナ取得成功?}
    N -->|Yes| O[mount container, true, namespace]
    N -->|No| P[何もしない]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-11-01 | ハイドレーションモード強制 | mount時にisHydrate=trueが常に渡される | createSSRAppで生成されたアプリのmount時 |
| BR-11-02 | レンダラーの遅延初期化 | ハイドレーションレンダラーは初回呼び出し時にのみ生成される | 未初期化の状態でcreateSSRAppが呼ばれた時 |
| BR-11-03 | コンテナ内容の保持 | createApp()と異なり、マウント時にコンテナのinnerHTMLをクリアしない | SSRでレンダリング済みHTMLを再利用するため |

### 計算ロジック

特に複雑な計算ロジックは存在しない。

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

該当なし（フロントエンドAPIのためDB操作は行わない）。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 警告（DEV） | mount対象セレクターがnullを返した場合 | 正しいCSSセレクターを指定する |
| - | 警告（DEV） | rootPropsがオブジェクトでない場合 | オブジェクト形式でPropsを渡す |
| - | 警告（DEV） | closed modeのShadowRootにマウントした場合 | mode: "open"を使用する |

### リトライ仕様

リトライ機構は存在しない。

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

該当なし。

## パフォーマンス要件

- ハイドレーションレンダラーは遅延初期化（lazy initialization）パターンで生成され、reactivity APIのみを使用する場合はtree-shakingにより除外される。

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

- `normalizeContainer()` はCSSセレクターを `document.querySelector()` に渡すため、ユーザー入力をそのままセレクターとして使用しないこと。

## 備考

- `createSSRApp()` と `createApp()` の主な違いは、mountメソッドがハイドレーションモード（`isHydrate=true`）で動作する点と、コンテナ内容をクリアしない点である。
- `createApp()` はmount時にcontainer.textContentを空にし、`v-cloak`属性を削除、`data-v-app`属性を付与するが、`createSSRApp()` ではこれらの処理は行われない。

---

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

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

### 推奨読解順序

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

まず、Appインスタンスのインターフェースと、AppContextの構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | apiCreateApp.ts | `packages/runtime-core/src/apiCreateApp.ts` | App, AppConfig, AppContextインターフェースの定義（33-206行目） |
| 1-2 | renderer.ts | `packages/runtime-core/src/renderer.ts` | Renderer, HydrationRendererインターフェースの定義（91-98行目） |

**読解のコツ**: `App` インターフェースには公開APIメソッド（`use`, `mount`, `unmount`, `provide`等）と内部プロパティ（`_uid`, `_component`, `_container`等）がある。`_`プレフィックス付きのプロパティは内部実装用。

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

`createSSRApp()` のエントリーポイントは `@vue/runtime-dom` パッケージの `index.ts`。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.ts | `packages/runtime-dom/src/index.ts` | createSSRAppの定義（148-165行目） |

**主要処理フロー**:
1. **148行目**: `createSSRApp` の関数定義開始
2. **149行目**: `ensureHydrationRenderer().createApp(...args)` でハイドレーション対応レンダラーからAppインスタンス生成
3. **151-154行目**: DEVモード時にネイティブタグチェックとコンパイラオプションチェックを注入
4. **156行目**: 元の `mount` メソッドを退避
5. **157-162行目**: `mount` メソッドをオーバーライド、`normalizeContainer()` でコンテナ解決後 `mount(container, true, ...)` でハイドレーションモードマウント

#### Step 3: ハイドレーションレンダラーの初期化を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | index.ts | `packages/runtime-dom/src/index.ts` | ensureHydrationRenderer関数（81-87行目） |

**主要処理フロー**:
- **82-84行目**: enabledHydrationフラグでハイドレーションレンダラーの初期化状態を管理。未初期化の場合のみ `createHydrationRenderer(rendererOptions)` を呼び出す
- **86行目**: HydrationRendererとしてキャストして返却

#### Step 4: createAppAPIの内部実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | apiCreateApp.ts | `packages/runtime-core/src/apiCreateApp.ts` | createAppAPI関数（253-487行目） |

**主要処理フロー**:
- **257行目**: createApp関数の本体。rootComponentとrootPropsを受け取る
- **267行目**: `createAppContext()` でアプリケーションコンテキストを初期化
- **273行目**: Appオブジェクトの構築（use, mixin, component, directive, mount, unmount, provide, runWithContext）
- **358-418行目**: mount メソッドの実装。`isHydrate && hydrate` の場合はハイドレーション、そうでなければ通常のレンダリング

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

```
createSSRApp(rootComponent, rootProps?)
    │
    ├─ ensureHydrationRenderer()
    │      └─ createHydrationRenderer(rendererOptions)
    │             └─ createHydrationFunctions()
    │
    ├─ renderer.createApp() → createAppAPI(render, hydrate)
    │      └─ createApp(rootComponent, rootProps)
    │             ├─ createAppContext()
    │             └─ App オブジェクト構築
    │
    ├─ [DEV] injectNativeTagCheck(app)
    ├─ [DEV] injectCompilerOptionsCheck(app)
    │
    └─ app.mount オーバーライド
           └─ normalizeContainer(containerOrSelector)
                  └─ document.querySelector() or direct use
```

### データフロー図

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

rootComponent ──────▶ ensureHydrationRenderer() ───▶ HydrationRenderer
rootProps     ──────▶ renderer.createApp()      ───▶ App Instance
                     mount override             ───▶ app.mount(container, true, namespace)
                                                        │
containerOrSelector ▶ normalizeContainer()      ───▶ Element | ShadowRoot
                     hydrate(vnode, container)   ───▶ Hydrated DOM
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.ts | `packages/runtime-dom/src/index.ts` | ソース | createSSRAppのエントリーポイント、mount/renderのDOM向け実装 |
| apiCreateApp.ts | `packages/runtime-core/src/apiCreateApp.ts` | ソース | App, AppContext, createAppAPIの定義 |
| renderer.ts | `packages/runtime-core/src/renderer.ts` | ソース | Renderer, HydrationRendererの型定義、setupRenderEffect |
| hydration.ts | `packages/runtime-core/src/hydration.ts` | ソース | ハイドレーション関数の実装（createHydrationFunctions） |
| nodeOps.ts | `packages/runtime-dom/src/nodeOps.ts` | ソース | DOM操作のプラットフォーム固有実装 |
| patchProp.ts | `packages/runtime-dom/src/patchProp.ts` | ソース | DOM属性パッチの実装 |
