# 機能設計書 58-@vue/compiler-ssr

## 概要

本ドキュメントは、@vue/compiler-ssrパッケージの処理について記述する。サーバーサイドレンダリング（SSR）向けに最適化されたテンプレートコンパイルを行い、HTML文字列出力に特化したコード生成を実現する。

### 本機能の処理概要

@vue/compiler-ssrは、Vueテンプレートを@vue/compiler-coreの変換インフラを使用しつつ、SSR専用の変換プラグインとコード生成を提供する。クライアント側のVNode生成コードではなく、テンプレートリテラルベースのHTML文字列生成コードを出力する。これにより、SSR時のパフォーマンスが最適化される。

**業務上の目的・背景**：SSRでは、コンポーネントツリーをHTML文字列に変換してクライアントに送信する。VNodeを生成してからシリアライズするよりも、直接HTML文字列を生成する方が効率的である。@vue/compiler-ssrはこの目的のために、テンプレートをテンプレートリテラル（`` `<div>${expr}</div>` ``）ベースの`_push()`呼び出しコードに変換する。

**機能の利用シーン**：compileTemplate()のSSRモード（ssr: true）で自動的に使用される。NuxtやViteのSSRビルドでテンプレートをコンパイルする際に呼び出される。

**主要な処理内容**：
1. @vue/compiler-coreの変換パイプラインにSSR専用のNodeTransformを登録
2. SSR専用のDirectiveTransformの登録（v-model、v-show）
3. SSRコード生成変換（ssrCodegenTransform）によるAST変換
4. テンプレートリテラルベースの_push()呼び出しコード生成
5. CSS変数の注入
6. フォールスルー属性の注入
7. 各コンポーネント/要素/スロットのSSR向け変換

**関連システム・外部連携**：@vue/compiler-coreおよび@vue/compiler-domの変換インフラを基盤として使用。@vue/server-rendererが生成されたSSRレンダリング関数を実行する。

**権限による制御**：該当なし（コンパイル時処理）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 5 | Options Panel（コンパイルオプション） | API連携 | SSRモード有効時のサーバーサイドレンダリング向けコンパイル切り替え |

## 機能種別

SSR向けテンプレートコンパイル処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| source | string \| RootNode | Yes | テンプレートソースまたは事前解析済みAST | - |
| options | CompilerOptions | No | コンパイラオプション | デフォルト: {} |

### 入力データソース

テンプレートソース文字列、またはbaseParse()で生成された事前解析済みRootNode。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| code | string | SSR用レンダリング関数のJavaScriptコード |
| ast | RootNode | 変換済みAST |
| preamble | string | プリアンブルコード |
| map | RawSourceMap | ソースマップ |

### 出力先

CodegenResultとして返却される。@vue/server-rendererのssrRenderとして実行される。

## 処理フロー

### 処理シーケンス

```
1. オプションの設定
   └─ ssr: true, inSSR: true
   └─ prefixIdentifiers: true（SSRではサイズ懸念なし）
   └─ cacheHandlers: false（SSRでは不要）
   └─ hoistStatic: false（SSRでは不要）

2. AST生成（ソース文字列の場合）
   └─ baseParse(source, options)

3. rawOptionsMapへのオプション保存
   └─ スロットVNodeブランチのサブ変換で使用

4. transform()の実行
   └─ nodeTransforms:
      - transformVBindShorthand
      - ssrTransformIf
      - ssrTransformFor
      - trackVForSlotScopes
      - transformExpression
      - ssrTransformSlotOutlet
      - ssrInjectFallthroughAttrs
      - ssrInjectCssVars
      - ssrTransformElement
      - ssrTransformComponent
      - trackSlotScopes
      - transformStyle
      - ユーザー定義のnodeTransforms
   └─ directiveTransforms:
      - bind: transformBind（コア再利用）
      - on: transformOn（コア再利用）
      - model: ssrTransformModel
      - show: ssrTransformShow
      - cloak/once/memo: noopDirectiveTransform

5. ssrCodegenTransform()の実行
   └─ テンプレートASTをSSRコード生成ASTに変換
   └─ _push()呼び出しのBlockStatementに変換
   └─ テンプレートリテラルによるHTML文字列連結
   └─ SSR補間（ssrInterpolate）の適用
   └─ CSS変数の注入

6. generate()の実行
   └─ コード生成ASTからJavaScriptコードを出力
```

### フローチャート

```mermaid
flowchart TD
    A[開始: compile] --> B{ソース文字列?}
    B -->|Yes| C[baseParse AST生成]
    B -->|No| D[AST直接使用]
    C --> E[rawOptionsMap保存]
    D --> E
    E --> F[transform SSR変換]
    F --> G[ssrCodegenTransform]
    G --> H[generate コード生成]
    H --> I[CodegenResult返却]
    I --> J[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-58-01 | SSR専用設定 | cacheHandlers=false, hoistStatic=false | SSRモード時は常時 |
| BR-58-02 | プレフィックス必須 | prefixIdentifiers=true（サイズ懸念なし） | SSRモード時は常時 |
| BR-58-03 | scopeId制限 | mode='function'の場合はscopeId=null | 関数モード時 |
| BR-58-04 | v-on SSR除外 | v-onイベントリスナーはSSRでは無視 | SSRモード時（ただしbind/on/model/showは例外） |
| BR-58-05 | cloak/once/memo無効 | v-cloak/v-once/v-memoはSSRで無効化 | SSRモード時は常時 |

### 計算ロジック

SSRヘルパーの分離:
- `ast.ssrHelpers`: '@vue/server-renderer'からインポートすべきヘルパー
- `ast.helpers`: 'vue'からインポートすべきヘルパー

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

該当なし（コンパイル時処理）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| X_SSR_INVALID_AST_NODE | SSRコンパイルエラー | SSR処理で非対応のASTノード | テンプレートを確認する |

### リトライ仕様

該当なし

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

該当なし（コンパイル時処理）

## パフォーマンス要件

- テンプレートリテラルベースのコード生成により、VNode生成のオーバーヘッドを回避
- cacheHandlersとhoistStaticを無効化することで、不要なコンパイル処理を省略
- 文字列連結の最適化（連続する静的テキストの結合）

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

- SSR出力のHTMLはescapeHtmlで適切にエスケープされる
- コメントはescapeHtmlCommentで安全に処理される

## 備考

- SSRコンパイラはクライアント側コンパイラとは異なるコード生成アプローチを採用する（VNodeCallではなくBlockStatement/TemplateLiteral）
- rawOptionsMapはスロットのサブ変換でクライアント側コードを生成する際に元のオプションを参照するために使用される
- v-modelとv-showにはSSR専用のDirectiveTransformが存在する（ssrTransformModel、ssrTransformShow）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | runtimeHelpers.ts | `packages/compiler-ssr/src/runtimeHelpers.ts` | SSRヘルパーシンボル定義（SSR_INTERPOLATE等） |
| 1-2 | ssrCodegenTransform.ts | `packages/compiler-ssr/src/ssrCodegenTransform.ts` | SSRTransformContext型定義 |

**読解のコツ**: SSRのコード生成はBlockStatement内にTemplateLiteralを含む_push()呼び出しの形式で行われる。pushStringPartで連続する文字列を結合し、pushStatementで制御フローを挿入する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.ts | `packages/compiler-ssr/src/index.ts` | compile()関数 |

**主要処理フロー**:
1. **32-47行目**: SSR固有のオプション設定（ssr:true, prefixIdentifiers:true, cacheHandlers:false等）
2. **49行目**: ソース文字列の場合はbaseParseでAST生成
3. **53行目**: rawOptionsMapにオプションを保存
4. **55-87行目**: transform()にSSR専用のnodeTransformsとdirectiveTransformsを登録
5. **91行目**: ssrCodegenTransform()でSSRコード生成AST変換
6. **93行目**: generate()でJavaScriptコードを出力

#### Step 3: SSRコード生成変換の詳細

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ssrCodegenTransform.ts | `packages/compiler-ssr/src/ssrCodegenTransform.ts` | ssrCodegenTransform関数 |

**主要処理フロー**:
- **38-76行目**: SSRコード生成変換のメイン処理。CSS変数の注入、子ノードの処理、ヘルパーの分離
- **90-135行目**: createSSRTransformContext - pushStringPart/pushStatementによるテンプレートリテラル構築
- **154-240行目**: processChildren - ノード種別ごとのSSR処理関数への振り分け

#### Step 4: 各SSR変換プラグインの理解

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ssrTransformElement.ts | `packages/compiler-ssr/src/transforms/ssrTransformElement.ts` | 要素のSSR変換（HTML文字列生成） |
| 4-2 | ssrTransformComponent.ts | `packages/compiler-ssr/src/transforms/ssrTransformComponent.ts` | コンポーネントのSSR変換 |
| 4-3 | ssrVIf.ts | `packages/compiler-ssr/src/transforms/ssrVIf.ts` | v-ifのSSR変換（if文生成） |
| 4-4 | ssrVFor.ts | `packages/compiler-ssr/src/transforms/ssrVFor.ts` | v-forのSSR変換（ループ生成） |
| 4-5 | ssrVModel.ts | `packages/compiler-ssr/src/transforms/ssrVModel.ts` | v-modelのSSR変換 |
| 4-6 | ssrVShow.ts | `packages/compiler-ssr/src/transforms/ssrVShow.ts` | v-showのSSR変換 |

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

```
compile (エントリーポイント)
    │
    ├─ baseParse (AST生成)
    │
    ├─ transform (変換パイプライン)
    │      ├─ ssrTransformIf
    │      ├─ ssrTransformFor
    │      ├─ transformExpression
    │      ├─ ssrTransformSlotOutlet
    │      ├─ ssrInjectFallthroughAttrs
    │      ├─ ssrInjectCssVars
    │      ├─ ssrTransformElement
    │      ├─ ssrTransformComponent
    │      ├─ trackSlotScopes
    │      └─ directiveTransforms
    │             ├─ ssrTransformModel
    │             └─ ssrTransformShow
    │
    ├─ ssrCodegenTransform
    │      ├─ processChildren
    │      │      ├─ ssrProcessElement
    │      │      ├─ ssrProcessComponent
    │      │      ├─ ssrProcessSlotOutlet
    │      │      ├─ ssrProcessIf
    │      │      └─ ssrProcessFor
    │      └─ createBlockStatement
    │
    └─ generate (コード生成)
```

### データフロー図

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

テンプレート        ───▶ compile()               ───▶ CodegenResult
(ソース/AST)              │                            ├─ code
                         ├─ baseParse                  │   function ssrRender(
                         │   → RootNode                │     _ctx, _push, ...
                         │                            │   ) {
                         ├─ transform                  │     _push(`<div>...`)
                         │   SSR NodeTransforms        │   }
                         │                            ├─ ast
                         ├─ ssrCodegenTransform        ├─ preamble
                         │   AST → BlockStatement      └─ map
                         │   _push(TemplateLiteral)
                         │
                         └─ generate
                             → JavaScript出力
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.ts | `packages/compiler-ssr/src/index.ts` | ソース | SSRコンパイラのエントリーポイント |
| ssrCodegenTransform.ts | `packages/compiler-ssr/src/ssrCodegenTransform.ts` | ソース | SSRコード生成AST変換 |
| runtimeHelpers.ts | `packages/compiler-ssr/src/runtimeHelpers.ts` | ソース | SSRヘルパーシンボル定義 |
| errors.ts | `packages/compiler-ssr/src/errors.ts` | ソース | SSRエラーコード定義 |
| ssrTransformElement.ts | `packages/compiler-ssr/src/transforms/ssrTransformElement.ts` | ソース | 要素のSSR変換 |
| ssrTransformComponent.ts | `packages/compiler-ssr/src/transforms/ssrTransformComponent.ts` | ソース | コンポーネントのSSR変換 |
| ssrTransformSlotOutlet.ts | `packages/compiler-ssr/src/transforms/ssrTransformSlotOutlet.ts` | ソース | スロットアウトレットのSSR変換 |
| ssrVIf.ts | `packages/compiler-ssr/src/transforms/ssrVIf.ts` | ソース | v-ifのSSR変換 |
| ssrVFor.ts | `packages/compiler-ssr/src/transforms/ssrVFor.ts` | ソース | v-forのSSR変換 |
| ssrVModel.ts | `packages/compiler-ssr/src/transforms/ssrVModel.ts` | ソース | v-modelのSSR変換 |
| ssrVShow.ts | `packages/compiler-ssr/src/transforms/ssrVShow.ts` | ソース | v-showのSSR変換 |
| ssrInjectFallthroughAttrs.ts | `packages/compiler-ssr/src/transforms/ssrInjectFallthroughAttrs.ts` | ソース | フォールスルー属性の注入 |
| ssrInjectCssVars.ts | `packages/compiler-ssr/src/transforms/ssrInjectCssVars.ts` | ソース | CSS変数の注入 |
| ssrTransformTeleport.ts | `packages/compiler-ssr/src/transforms/ssrTransformTeleport.ts` | ソース | TeleportのSSR変換 |
| ssrTransformSuspense.ts | `packages/compiler-ssr/src/transforms/ssrTransformSuspense.ts` | ソース | SuspenseのSSR変換 |
| ssrTransformTransition.ts | `packages/compiler-ssr/src/transforms/ssrTransformTransition.ts` | ソース | TransitionのSSR変換 |
