# 帳票設計書 25-_ssgManifest.js

## 概要

本ドキュメントは、Next.jsビルドプロセスにおいて生成される `_ssgManifest.js` の設計仕様を定義する。このファイルはSSG（Static Site Generation）対象ページの一覧をクライアント側で利用可能にするマニフェストである。

### 本帳票の処理概要

`_ssgManifest.js` は、Next.jsのプロダクションビルド時に生成されるクライアントサイドJavaScriptファイルで、ISR/SSGで事前レンダリングされたページの一覧をSetオブジェクトとして保持する。クライアントサイドルーターがナビゲーション時にデータフェッチの必要性を判断するために使用される。

**業務上の目的・背景**：クライアントサイドナビゲーション時に、遷移先ページがSSG対象かどうかを判定する必要がある。SSG対象ページの場合、サーバーに対してJSONデータフェッチを行う必要があるため、事前にSSG対象ページの一覧をクライアントに提供することで、適切なデータフェッチ戦略を選択できるようにする。

**帳票の利用シーン**：ブラウザでのクライアントサイドナビゲーション時に、Next.jsのクライアントランタイムが参照する。ページ遷移時にSSGデータの取得が必要かどうかの判定に使用される。

**主要な出力内容**：
1. SSG対象ページのパスセット（`self.__SSG_MANIFEST`）
2. コールバック通知（`self.__SSG_MANIFEST_CB`）

**帳票の出力タイミング**：`next build` コマンドによるプロダクションビルドの最終段階で、プリレンダリングマニフェスト書き込み後に生成される。

**帳票の利用者**：Next.jsクライアントサイドランタイム（ルーターモジュール）

## 帳票種別

ビルドメタ情報（クライアントサイドJavaScriptマニフェスト）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| N/A | CLIコマンド | `next build` | ビルド実行時に自動生成 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | JavaScript |
| 用紙サイズ | N/A（データファイル） |
| 向き | N/A |
| ファイル名 | _ssgManifest.js |
| 出力方法 | ファイルシステムへの書き込み |
| 文字コード | UTF-8 |

## 帳票レイアウト

### レイアウト概要

自己実行型JavaScriptコード。`self.__SSG_MANIFEST` にSSGページのSetをアサインし、コールバック関数があれば呼び出す。

```javascript
self.__SSG_MANIFEST=new Set(["/page1","/page2"]);self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB()
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | __SSG_MANIFEST | SSG対象ページのパスセット | prerenderManifest.routes + prerenderManifest.dynamicRoutes | Set（devalue形式でシリアライズ） |
| 2 | __SSG_MANIFEST_CB | マニフェスト読み込み完了コールバック | N/A（存在確認のみ） | 関数呼び出し |

### 明細部

N/A

### フッター部

N/A

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| プロダクションビルド | `next build` コマンドが実行されていること | Yes |
| プリレンダリングマニフェスト | prerenderManifestが存在すること | Yes |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | ページパス | 昇順（Array.sort()によるデフォルトソート） |

### 改ページ条件

N/A

## データベース参照仕様

### 参照テーブル一覧

N/A（データベースを使用しない。prerenderManifestからデータを取得する）

### テーブル別参照項目詳細

N/A

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| ssgPages | prerenderManifest.routesの静的ルート（srcRoute == null）をnormalizeLocalePath適用後 + prerenderManifest.dynamicRoutesのキー、をSetに変換 | N/A | 重複排除はSetにより自動的に行われる |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[next build完了間際] --> B[writePrerenderManifest完了]
    B --> C[writeClientSsgManifest呼び出し]
    C --> D[prerenderManifest.routesから静的ルート抽出]
    D --> E[srcRoute == nullのフィルタ]
    E --> F[normalizeLocalePathでロケール正規化]
    F --> G[prerenderManifest.dynamicRoutesのキー取得]
    G --> H[Setに統合・ソート]
    H --> I[devalueでシリアライズ]
    I --> J{deploymentId存在?}
    J -->|Yes| K[static/_ssgManifest.jsに書き込み]
    J -->|No| L[static/buildId/_ssgManifest.jsに書き込み]
    K --> M[終了]
    L --> M
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| 書き込み失敗 | distDirへのファイルシステム書き込み権限なし | ファイルシステムエラー | distDirのパーミッション確認 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | SSG対象ページ数に依存（数件〜数千件） |
| 目標出力時間 | ミリ秒オーダー |
| 同時出力数上限 | 1（ビルドプロセスにつき1回） |

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

- アプリケーションのルーティング構造（SSG対象ページ一覧）が公開されるため、URLパスの秘匿性が必要な場合は注意
- クライアントに配信されるJavaScriptファイルであるため、一般ユーザーから閲覧可能

## 備考

- 出力先: `.next/static/[buildId]/_ssgManifest.js` または `.next/static/_ssgManifest.js`（deploymentId指定時）
- deploymentId（skew protection）が有効な場合、buildIdディレクトリを介さずstaticディレクトリ直下に配置される
- `devalue` ライブラリを使用してSetオブジェクトをシリアライズ
- `__SSG_MANIFEST_CB` コールバックパターンにより、非同期読み込みに対応

---

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

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

### 推奨読解順序

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

SSGマニフェストのデータソースであるprerenderManifestの構造を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | index.ts | `packages/next/src/build/index.ts` | prerenderManifest.routesとprerenderManifest.dynamicRoutesの構造。routesの各エントリはsrcRouteプロパティを持つ |

**読解のコツ**: `srcRoute == null` のフィルタは、動的ルートから生成された個別ページ（例：`/blog/1`）を除外し、静的に定義されたルートのみを抽出する処理。

#### Step 2: 生成処理を理解する

`writeClientSsgManifest` 関数の実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.ts | `packages/next/src/build/index.ts` | L557-595: `writeClientSsgManifest` 関数の全体。SSGページセットの構築、devalueによるシリアライズ、ファイル出力 |

**主要処理フロー**:
1. **L571-578**: `ssgPages` Setの構築。routesからsrcRoute==nullのフィルタ + normalizeLocalePath適用、dynamicRoutesのキー追加、ソート
2. **L581-583**: `clientSsgManifestContent` の生成。`self.__SSG_MANIFEST=${devalue(ssgPages)};self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB()`
3. **L587-589**: 出力パスの決定。deploymentId有無で分岐
4. **L591-594**: `writeFileUtf8` でファイル書き込み

#### Step 3: 呼び出し箇所を理解する

ビルドメインフローからの呼び出しを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | index.ts | `packages/next/src/build/index.ts` | L4101-4106: `writeClientSsgManifest(prerenderManifest, {distDir, buildId, locales, deploymentId})` 呼び出し |

#### Step 4: クライアントサイド参照を理解する

クライアントランタイムでの参照箇所を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | build-manifest-plugin.ts | `packages/next/src/build/webpack/plugins/build-manifest-plugin.ts` | `_ssgManifest.js` のアセット登録処理 |
| 4-2 | manifest-loader.ts | `packages/next/src/shared/lib/turbopack/manifest-loader.ts` | Turbopack使用時のマニフェスト読み込み |

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

```
next build (CLI)
    |
    +-- build/index.ts (メインビルドフロー)
           |
           +-- writePrerenderManifest()
           |
           +-- writeClientSsgManifest()  <-- 生成
           |      |
           |      +-- prerenderManifest.routes フィルタリング
           |      +-- normalizeLocalePath()
           |      +-- prerenderManifest.dynamicRoutes キー取得
           |      +-- devalue() シリアライズ
           |      +-- writeFileUtf8() 書き込み
           |
           +-- [後続処理...]

ブラウザ (クライアントサイド)
    |
    +-- <script src="/_next/static/[buildId]/_ssgManifest.js">
           |
           +-- self.__SSG_MANIFEST = Set
           +-- self.__SSG_MANIFEST_CB() コールバック
```

### データフロー図

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

prerenderManifest.routes -----+
  (srcRoute == null フィルタ)   |
                               +---> writeClientSsgManifest()
prerenderManifest              |     devalue(ssgPages)        ------> .next/static/[buildId]/_ssgManifest.js
  .dynamicRoutes           ----+
  (キーのみ抽出)

config.i18n.locales ---------> normalizeLocalePath()
config.deploymentId ---------> 出力パス決定
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.ts | `packages/next/src/build/index.ts` | ソース | writeClientSsgManifest関数定義（L557-595）、呼び出し（L4101） |
| build-manifest-plugin.ts | `packages/next/src/build/webpack/plugins/build-manifest-plugin.ts` | ソース | _ssgManifest.jsのWebpackアセット登録 |
| manifest-loader.ts | `packages/next/src/shared/lib/turbopack/manifest-loader.ts` | ソース | Turbopack時のマニフェスト読み込み |
