# 通知設計書 38-バージョン古さ通知

## 概要

本ドキュメントは、Next.js開発サーバーにおけるバージョン古さ通知の設計について記載する。インストールされているNext.jsバージョンが最新でない場合にDev Overlay内でバージョン情報と更新推奨を表示する通知機能である。

### 本通知の処理概要

バージョン古さ通知は、インストールされているNext.jsのバージョンと、npmレジストリ上の最新バージョンを比較し、古い場合にDev Overlayのナビゲーションバー内にバージョン情報とステータスインジケーターを表示する機能である。

**業務上の目的・背景**：Next.jsはフレームワークとして頻繁にアップデートされ、バグ修正、パフォーマンス改善、セキュリティ修正が含まれる。開発者が古いバージョンを使い続けることは、既知の問題に遭遇するリスクを高める。本通知により、開発者が現在のバージョンの鮮度を常に把握でき、適切なタイミングでアップデートを実施できるようにする。

**通知の送信タイミング**：Dev Overlayが表示される際に常時表示される。バージョン情報は開発サーバー起動時に`parseVersionInfo()`で算出され、`OverlayState.versionInfo`として保持される。

**通知の受信者**：開発中のアプリケーションをブラウザで表示し、Dev Overlayを確認している開発者。

**通知内容の概要**：4段階の鮮度ステータス（fresh / stale-patch/minor / stale-major / stale-prerelease）に応じたバージョン表示とカラーインジケーター、バンドラー名（Webpack/Turbopack/Rspack）、更新推奨メッセージが表示される。古い場合はNext.jsのバージョンドキュメントへのリンクが提供される。

**期待されるアクション**：バージョンが古い場合、開発者はNext.jsのアップデートを検討する。特にstale-major（メジャーバージョンが古い）の場合は「highly recommended」として強い推奨が表示される。

## 通知種別

ブラウザUI / Dev Overlay（ナビゲーションバー内インジケーター）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（Dev Overlay描画時に常時表示） |
| 優先度 | 低（情報提供のみ、エラー表示を妨げない） |
| リトライ | 無し |

### 送信先決定ロジック

Dev Overlayが描画されるすべてのブラウザクライアントに対して表示される。`ErrorOverlayLayout`コンポーネント内の`ErrorOverlayNav`がバージョン情報を受け取り、`VersionStalenessInfo`コンポーネントで表示する。

## 通知テンプレート

### ブラウザUI表示の場合

| 項目 | 内容 |
|-----|------|
| インジケーターアイコン | EclipseIcon（色はステータスに応じて変化） |
| バージョンテキスト | Next.js {version} / Next.js {version} (stale) / Next.js {version} (outdated) |
| バンドラー名 | Webpack / Turbopack / Rspack |
| リンク | https://nextjs.org/docs/messages/version-staleness（stale時のみ） |
| 形式 | ナビゲーションバー内インラインバッジ |

### 本文テンプレート

ステータス別の表示パターン：

| ステータス | テキスト | タイトル（ツールチップ） | インジケーター色 |
|-----------|---------|----------------------|----------------|
| fresh / newer-than-npm | Next.js {version} | Latest available version is detected ({version}). | 緑（fresh） |
| stale-patch / stale-minor | Next.js {version} (stale) | There is a newer version ({expected}) available, upgrade recommended! | 黄（stale） |
| stale-major | Next.js {version} (outdated) | An outdated version detected (latest is {expected}), upgrade is highly recommended! | 赤（outdated） |
| stale-prerelease | Next.js {version} (stale) | There is a newer canary version ({expected}) available, please upgrade! | 黄（stale） |
| unknown | Next.js {version} (unknown) | No Next.js version data was found. | 灰（unknown） |

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| versionInfo.installed | インストール済みバージョン | parseVersionInfo() | Yes |
| versionInfo.staleness | 鮮度ステータス | parseVersionInfo() | Yes |
| versionInfo.expected | 期待されるバージョン | parseVersionInfo() | No（fresh時はなし） |
| bundlerName | バンドラー名 | process.env.TURBOPACK判定 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| コンポーネント描画 | Dev Overlay表示 | 常に表示 | Dev Overlayが描画されるたびにバージョン情報が表示される |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| Dev Overlayが表示されていない | エラーがない場合はDev Overlay自体が表示されないため、バージョン情報も表示されない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[開発サーバー起動] --> B[parseVersionInfo呼び出し]
    B --> C[semverでバージョン比較]
    C --> D{installed vs latest/canary}
    D -->|major古い| E[stale-major]
    D -->|canary古い| F[stale-prerelease]
    D -->|minor古い| G[stale-minor]
    D -->|patch古い| H[stale-patch]
    D -->|最新以上| I[fresh/newer-than-npm]
    D -->|判定不能| J[unknown]
    E --> K[OverlayState.versionInfo設定]
    F --> K
    G --> K
    H --> K
    I --> K
    J --> K
    K --> L[Dev Overlay描画時]
    L --> M[getStaleness呼び出し]
    M --> N[VersionStalenessInfo表示]
    N --> O{stale系?}
    O -->|Yes| P[リンク付き表示]
    O -->|No| Q[通常表示]
```

## データベース参照・更新仕様

### 参照テーブル一覧

該当なし（データベースは使用しない。npmレジストリからバージョン情報を取得する）

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| バージョン解析失敗 | installed/latest/canaryのいずれかがsemverとして解析できない場合 | staleness: 'unknown'を返す。installed値は'0.0.0'にフォールバック |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（リトライなし） |
| リトライ間隔 | 該当なし |
| リトライ対象エラー | 該当なし |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし（開発サーバー稼働中は常時表示可能）

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

- バージョン情報はNext.jsのパッケージバージョンのみであり、機密データは含まれない
- npmレジストリへの通信はバージョン情報取得のみであり、プロジェクトの情報は送信されない
- Dev Overlayは本番ビルドには含まれない

## 備考

- `parseVersionInfo()`はsemverライブラリを使用してバージョン比較を行う
- バージョン判定の優先順序：stale-major > stale-prerelease > stale-minor/stale-patch > fresh/newer-than-npm
- canaryバージョン（prerelease[0] === 'canary'）の場合はstale-prereleaseとして判定される
- Turbopackの場合、バンドラー名がグラデーションテキスト（turbopack-text CSSクラス）で表示される
- stale系のステータスの場合はリンク（`<a>`タグ）として描画され、クリックでNext.jsのバージョンドキュメントが開く

---

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

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

### 推奨読解順序

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

まず、バージョン情報のデータ構造と解析ロジックを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | parse-version-info.ts | `packages/next/src/server/dev/parse-version-info.ts` | `VersionInfo`インターフェース（3-14行目）。`installed`, `staleness`, `expected`の3フィールド。`staleness`は7種類の文字列リテラル |
| 1-2 | parse-version-info.ts | `packages/next/src/server/dev/parse-version-info.ts` | `parseVersionInfo()`関数（16-69行目）。semverを使ったバージョン比較ロジック |

**読解のコツ**: `parseVersionInfo()`はinstalled/latest/canaryの3つのバージョン文字列を入力として受け取り、比較ロジックで7種類のstalenessのいずれかを返す。判定順序がバグの原因になりやすいため、条件分岐の順序に注意。

#### Step 2: ステータステキスト生成を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | version-staleness.ts | `packages/next/src/next-devtools/shared/version-staleness.ts` | `getStaleness()`関数（3-42行目）。stalenessに応じたtext、title、indicatorClassの生成 |

**主要処理フロー**:
- **8行目**: switch文でstalenessの各値に対応
- **10-12行目**: fresh/newer-than-npm: テキストのみ、indicatorClass='fresh'
- **16-19行目**: stale-patch/stale-minor: '(stale)'サフィックス、indicatorClass='stale'
- **21-25行目**: stale-major: '(outdated)'サフィックス、indicatorClass='outdated'
- **27-30行目**: stale-prerelease: '(stale)'サフィックス、indicatorClass='stale'
- **33-36行目**: unknown: '(unknown)'サフィックス、indicatorClass='unknown'

#### Step 3: UIコンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | version-staleness-info.tsx | `packages/next/src/next-devtools/dev-overlay/components/version-staleness-info/version-staleness-info.tsx` | `VersionStalenessInfo`コンポーネント（6-51行目）。stale系の場合はリンク（`<a>`）、それ以外はspan表示 |

**主要処理フロー**:
- **18行目**: `staleness.startsWith('stale')`でリンク表示かどうかを判定
- **19-37行目**: stale系の場合は`<a>`タグでhttps://nextjs.org/docs/messages/version-stalenessへのリンク
- **40-50行目**: それ以外は`<span>`タグで表示

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

```
開発サーバー起動
    |
    +-- parseVersionInfo() [parse-version-info.ts:16]
           +-- semver.parse() / semver.lt() / semver.gt()
    |
    v
OverlayState.versionInfo設定
    |
    v
ErrorOverlayLayout [error-overlay-layout.tsx:58]
    |
    +-- ErrorOverlayNav
           +-- VersionStalenessInfo [version-staleness-info.tsx:6]
                  +-- getStaleness() [version-staleness.ts:3]
                  +-- EclipseIcon (カラーインジケーター)
```

### データフロー図

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

npmレジストリ              parseVersionInfo()                 ブラウザ
(latest/canary)  ------>  semverバージョン比較           ----> Dev Overlay内
                          VersionInfo生成                     バージョンバッジ
package.json               getStaleness()                     (インジケーター色 +
(installed)      ------>  text/title/indicatorClass生成        テキスト +
                          VersionStalenessInfo描画             リンク)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| parse-version-info.ts | `packages/next/src/server/dev/parse-version-info.ts` | ソース | VersionInfo型定義、parseVersionInfo関数。semverによるバージョン比較 |
| version-staleness.ts | `packages/next/src/next-devtools/shared/version-staleness.ts` | ソース | getStaleness関数。stalenessに応じた表示テキスト・色の決定 |
| version-staleness-info.tsx | `packages/next/src/next-devtools/dev-overlay/components/version-staleness-info/version-staleness-info.tsx` | ソース | VersionStalenessInfoコンポーネント。UIの描画 |
