# ライブコンポーネント

ライブコンポーネントは、`@lazarv/react-server` の強力な機能であり、ページ全体を再読み込みすることなくリアルタイムで更新できるインタラクティブなコンポーネントを作成できます。これはチャットアプリケーション、ダッシュボード、コラボレーションツールなどの動的なコンテンツ更新を必要とするアプリケーションで特に有用です。

> **注記:** ライブコンポーネントは `@lazarv/react-server` とシームレスに連携するよう設計されており、React Server Components の力を活用してスムーズで効率的なユーザー体験を提供します。ただし、これらはまだ実験的な機能であり、本番環境での使用には注意が必要です。

## なぜライブコンポーネントなのか？

ライブコンポーネントにはいくつかの利点があります。
- **リアルタイム更新:** ライブコンポーネントはデータの変更に応じて状態を更新し再レンダリングするため、シームレスなユーザー体験を提供します。
- **低遅延:** ページ全体の再読み込みを回避することで、ライブコンポーネントは更新をより迅速に提供し、アプリケーションの応答性を向上させます。
- **ユーザー体験の向上:** ユーザーは中断することなくアプリケーションと対話できるため、よりスムーズで没入感のある体験が実現します。
- **リモートコンポーネント:** ライブコンポーネントはリモートコンポーネントと連携して使用でき、リモートソースからコンポーネントをロード・レンダリングしながらリアルタイム更新の利点を維持できます。

## ライブコンポーネントの実装方法

アプリケーションにライブコンポーネントを実装するには、コンポーネント内で `"use live"` ディレクティブを使用します。このディレクティブによりコンポーネントはライブ状態となり、リアルタイムで更新が可能になります。コンポーネントは非同期ジェネレータ関数で実装し、React Server Componentとしてコンポーネントの更新をyieldする必要があります。

以下にライブコンポーネントのシンプルな使用例を示します。

```jsx
"use live";

export default async function* LiveComponent() {
  while (true) {
    yield <div>Current time: {new Date().toLocaleTimeString()}</div>;
    await new Promise((resolve) => setTimeout(resolve, 1000));
  }
}
```

ランタイムはこのコンポーネント用に特別なアウトレットを作成し、リアルタイムでの更新を可能にします。コンポーネントは毎秒再レンダリングされ、ページ全体の再読み込みやユーザーの操作を必要とせずに現在の時刻を表示します。

アプリケーションでライブコンポーネントを使用するには、他のReactコンポーネントと同様にインポートしてレンダリングします。

```jsx
import LiveComponent from "./LiveComponent";

export default function Home() {
  return (
    <div>
      <h1>Live Component Example</h1>
      <LiveComponent />
    </div>
  );
}
```

これによりページ上にライブコンポーネントが表示され、毎秒更新されて現在の時刻が表示されます。

ライブコンポーネントは、サーバ関数やクライアントコンポーネントなど `@lazarv/react-server` の他の機能と組み合わせて使用することも可能です。これによりユーザーの入力やデータ変更にリアルタイムで応答する、リッチでインタラクティブなアプリケーションを作成できます。

各ライブコンポーネントインスタンスは独自のコンテキストで実行されるため、同一ページ上に同一ライブコンポーネントの複数インスタンスを配置でき、それぞれが独自の状態と更新を保持します。これにより複数のライブ更新を同時に処理できる複雑なインタラクティブUIを作成できます。

> **注記:** ライブコンポーネント機能の最新情報にご期待ください。`"use live: broadcast"` がまもなく提供開始予定です。これにより複数のライブコンポーネントへの更新を一括で配信できるようになり、アプリケーション全体の状態と更新の管理が容易になります。

## Live I/O

ライブコンポーネントは、3つのトランスポートを標準でサポートしています。`react-server.config.{mjs,json}` で選択できます:

```mjs
export default {
  live: {
    transport: "auto", // "auto" | "socketio" | "sse" | "ws"
  },
};
```

| トランスポート | 説明 | 最適な用途 |
|---|---|---|
| `"auto"`（デフォルト） | エッジ／サーバーレスビルドでは `"sse"`、Nodeでは `"socketio"` を選択 | ほとんどのプロジェクト — デプロイ先に応じて適応 |
| `"socketio"` | [socket.io](https://socket.io/) による双方向WebSocket、アウトレット毎のネームスペース | Nodeデプロイメント、後方互換性 |
| `"sse"` | Server-Sent Events — HTTP/1.1ネイティブ、サーバー→クライアントのみ | Cloudflare Workers、Vercel Edge、WebSocketアップグレードをブロックする企業プロキシ |
| `"ws"` | ネイティブWebSocket（socket.ioなし）、軽量なクライアント | 低オーバーヘッドのNodeデプロイメント、socket.ioの再接続／フォールバック機能が不要な場合 |

> **コンポーネント単位の上書き:** 任意のモジュールは `"use live; transport=sse"` ディレクティブ形式で独自のトランスポートを指定できます。ビルドは実際に参照されたトランスポート名をすべて収集し、ランタイムでロードするのはそれらだけです。

```jsx
"use live; transport=sse";

export default async function* StockTicker() {
  for await (const tick of subscribeToTicks()) {
    yield <Tick {...tick} />;
  }
}
```

## 未使用時のゼロコスト

アプリケーションに `"use live"` モジュールがない場合、ランタイムにはトランスポートコードが**ゼロ**含まれます:

- ビルドはライブマニフェストを出力しないため、本番サーバーは `socket.io`（または `ws`、SSEアダプター）をインポートしません。
- ブラウザは `socket.io-client` をインポートしません — トランスポート毎のクライアントアダプターは、現在のページのアウトレットがライブの場合にのみ動的にインポートされます。
- HTMLのプリコネクトリンク（``）は、ライブアウトレットを持たないページからは完全に省略されます。

ページがライブコンポーネントを使用する場合、そのページが実際に必要とするトランスポートのみがロードされます — 単一のコンポーネントに `"use live; transport=sse"` を追加しても、socket.io がバンドルに引き込まれることはありません。