# 機能設計書 109-Web Vitals

## 概要

本ドキュメントは、Next.jsのWeb Vitals計測機能の設計を記述する。Core Web Vitals（LCP、FID、CLS等）をクライアントサイドで計測し、ユーザー定義のコールバックに通知するフック機能である。

### 本機能の処理概要

`useReportWebVitals`フックを通じて、ブラウザ上でCore Web Vitals指標（LCP、FID、CLS、INP、FCP、TTFB）を計測し、開発者が定義したコールバック関数に計測結果を通知するクライアントサイド機能である。`web-vitals`ライブラリをラップして提供する。

**業務上の目的・背景**：Webアプリケーションのユーザー体験を定量的に把握するために、Googleが提唱するCore Web Vitalsの計測が重要である。Next.jsは`web-vitals`ライブラリを統合し、開発者が最小限のコードでパフォーマンスメトリクスを収集できるようにしている。

**機能の利用シーン**：App RouterのレイアウトファイルまたはPages Routerの`_app.tsx`で`useReportWebVitals`フックを使用し、パフォーマンスメトリクスをアナリティクスサービス（Google Analytics、Vercel Analytics等）に送信する。

**主要な処理内容**：
1. `useEffect`フック内で各Web Vitals指標の監視を開始
2. LCP（Largest Contentful Paint）の計測
3. FID（First Input Delay）の計測
4. CLS（Cumulative Layout Shift）の計測
5. INP（Interaction to Next Paint）の計測
6. FCP（First Contentful Paint）の計測
7. TTFB（Time to First Byte）の計測
8. 各指標の計測完了時にユーザー定義のコールバック関数を呼び出し

**関連システム・外部連携**：`web-vitals`ライブラリ（コンパイル済み）に依存。計測結果の送信先はユーザーが自由に定義する。

**権限による制御**：クライアントサイドで動作するため、特別な権限制御はない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | すべてのページ | 主画面 | ページ表示・インタラクション時にWeb Vitals指標が計測される |

## 機能種別

計測・分析 / クライアントサイド処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| reportWebVitalsFn | (metric: Metric) => void | Yes | 計測結果を受け取るコールバック関数 | - |

### 入力データソース

- ブラウザのPerformance API（Performance Observer）
- ユーザーインタラクションイベント

## 出力仕様

### 出力データ（Metric型）

| 項目名 | 型 | 説明 |
|--------|-----|------|
| name | string | 指標名（LCP, FID, CLS, INP, FCP, TTFB） |
| value | number | 計測値（ミリ秒またはスコア） |
| rating | string | 評価（good, needs-improvement, poor） |
| delta | number | 前回値からの差分 |
| id | string | 計測の一意ID |
| entries | PerformanceEntry[] | 関連するPerformanceEntryの配列 |

### 出力先

ユーザー定義のコールバック関数（`reportWebVitalsFn`）

## 処理フロー

### 処理シーケンス

```
1. useReportWebVitalsフックがコンポーネントのマウント時に実行
   └─ useEffect内で各指標の監視を開始
2. onCLS(reportWebVitalsFn) - CLS監視開始
   └─ LayoutShift PerformanceEntryを監視
3. onFID(reportWebVitalsFn) - FID監視開始
   └─ First InputイベントのDelayを監視
4. onLCP(reportWebVitalsFn) - LCP監視開始
   └─ LargestContentfulPaint PerformanceEntryを監視
5. onINP(reportWebVitalsFn) - INP監視開始
   └─ Event Timing APIでインタラクション遅延を監視
6. onFCP(reportWebVitalsFn) - FCP監視開始
   └─ Paint Timing APIでFirst Contentful Paintを監視
7. onTTFB(reportWebVitalsFn) - TTFB監視開始
   └─ Navigation Timing APIでTime to First Byteを計測
8. 各指標が計測されるたびにreportWebVitalsFnが呼び出される
```

### フローチャート

```mermaid
flowchart TD
    A[useReportWebVitals] --> B[useEffect]
    B --> C[onCLS登録]
    B --> D[onFID登録]
    B --> E[onLCP登録]
    B --> F[onINP登録]
    B --> G[onFCP登録]
    B --> H[onTTFB登録]
    C --> I[PerformanceObserver]
    D --> I
    E --> I
    F --> I
    G --> I
    H --> I
    I --> J{指標計測完了?}
    J -->|Yes| K[reportWebVitalsFn呼び出し]
    K --> L[Metric情報渡し]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-109-1 | 6指標計測 | CLS, FID, LCP, INP, FCP, TTFBの6つのWeb Vitals指標を計測 | フック使用時 |
| BR-109-2 | マウント時のみ登録 | useEffect依存配列に[reportWebVitalsFn]を指定 | コンポーネントライフサイクル |
| BR-109-3 | コールバック更新対応 | reportWebVitalsFnが変更された場合、useEffectが再実行される | コールバック関数変更時 |

### 計算ロジック

各指標の計測はweb-vitalsライブラリに委譲される。計測値の単位:
- LCP: ミリ秒
- FID: ミリ秒
- CLS: スコア（単位なし）
- INP: ミリ秒
- FCP: ミリ秒
- TTFB: ミリ秒

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

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

該当なし。クライアントサイドのみの処理。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | API未対応 | ブラウザがPerformance Observer APIをサポートしない場合 | web-vitalsライブラリ内でエラーハンドリング（計測がスキップされる） |

### リトライ仕様

リトライは不要。計測はブラウザイベントに基づいて自動的に行われる。

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

該当なし。

## パフォーマンス要件

- Web Vitals計測自体がページパフォーマンスに影響を与えないよう、Performance Observer APIを使用（非ブロッキング）
- useEffectによるマウント後の非同期登録でレンダリングをブロックしない

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

- クライアントサイドでの計測データは、ユーザーのコールバック関数経由で送信先を制御
- 計測データにはユーザーの個人情報は含まれない

## 備考

- `web-vitals`ライブラリは`next/dist/compiled/web-vitals`としてコンパイル済みで含まれている
- App Routerで使用する場合は`'use client'`ディレクティブが必要
- FIDはINP（Interaction to Next Paint）に置き換えられつつあるが、後方互換性のため両方をサポート

---

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

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

### 推奨読解順序

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

web-vitalsライブラリのMetric型を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | web-vitals.ts | `packages/next/src/client/web-vitals.ts` | Metric型のインポート（10行目）とuseReportWebVitalsのシグネチャ |

**読解のコツ**: `Metric`型は`web-vitals`ライブラリで定義されており、name, value, rating, delta, id, entriesの各プロパティを持つ。Next.jsはこの型を再エクスポートしている。

#### Step 2: フック実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | web-vitals.ts | `packages/next/src/client/web-vitals.ts` | useReportWebVitalsフック（12-23行目） |

**主要処理フロー**:
1. **1行目**: `useEffect`をReactからインポート
2. **2-9行目**: web-vitalsライブラリから6つのon関数をインポート
3. **15行目**: `useEffect`フック内で処理を実行
4. **16-21行目**: 各on関数にコールバックを登録（onCLS, onFID, onLCP, onINP, onFCP, onTTFB）
5. **22行目**: 依存配列に`[reportWebVitalsFn]`を指定

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

```
App Layout / _app.tsx
    │
    └─ useReportWebVitals(callback)
           │
           └─ useEffect(() => { ... }, [callback])
                  ├─ onCLS(callback)
                  │      └─ PerformanceObserver('layout-shift')
                  ├─ onFID(callback)
                  │      └─ PerformanceObserver('first-input')
                  ├─ onLCP(callback)
                  │      └─ PerformanceObserver('largest-contentful-paint')
                  ├─ onINP(callback)
                  │      └─ PerformanceObserver('event')
                  ├─ onFCP(callback)
                  │      └─ PerformanceObserver('paint')
                  └─ onTTFB(callback)
                         └─ Navigation Timing API
```

### データフロー図

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

ブラウザイベント ──────> web-vitals ライブラリ ──────> Metric オブジェクト
  ├─ Layout Shift          ├─ onCLS()                    ├─ name: 'CLS'
  ├─ First Input           ├─ onFID()                    ├─ value: 0.1
  ├─ LCP Element           ├─ onLCP()                    ├─ rating: 'good'
  ├─ Event Timing          ├─ onINP()                    ├─ delta
  ├─ Paint                 ├─ onFCP()                    └─ entries[]
  └─ Navigation            └─ onTTFB()
                                   │
                                   └──────> reportWebVitalsFn(metric)
                                                    │
                                              ユーザー定義の送信処理
                                              (Analytics等)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| web-vitals.ts | `packages/next/src/client/web-vitals.ts` | ソース | useReportWebVitalsフックの実装 |
| web-vitals (compiled) | `packages/next/src/compiled/web-vitals/` | 依存ライブラリ | Core Web Vitals計測ライブラリ |
| config-shared.ts | `packages/next/src/server/config-shared.ts` | ソース | webVitalsAttribution設定の型定義 |
