# React

`@lazarv/react-server`にはReactが組み込まれています。`react`や`react-dom`を自分でインストールする**必要はありません** — ランタイムにはReact Server Components、サーバーアクション、およびすべての最新React機能をサポートする正しい実験的バージョンのReactが含まれています。

## Reactが組み込まれている理由

React Server Componentsには、RSCワイヤープロトコル、サーバー参照、ストリーミングサポートを含む実験的なReactビルドが必要です。これらの実験的APIは、npmに公開されている安定版リリースでは利用できません。`@lazarv/react-server`はビルド対象の正確なReactバージョンをバンドルすることで、以下を保証します:

- **正しいRSCサポート** — `react-server`エクスポート条件、`@lazarv/rsc`シリアライゼーションレイヤー、ストリーミングプリミティブがすべて一致します。
- **設定不要** — どの実験的Reactビルドをインストールすべきか、または`react`、`react-dom`、RSCシリアライゼーションレイヤー間で同期を保つ方法を考える必要はありません。
- **単一Reactインスタンス** — ランタイムは常に1つのReactコピーのみがロードされることを保証し、悪名高い「複数のReactインスタンス」バグ（フックの破損、コンテキストの破損など）を回避します。

## package.jsonにReactは不要

`@lazarv/react-server`でプロジェクトを作成する場合、`package.json`に`react`や`react-dom`を依存関係として記載する**べきではありません**:

```json filename="./package.json"
{
  "dependencies": {
    "@lazarv/react-server": "latest"
  }
}
```

これだけです。ランタイムがプロジェクト全体にReactを提供します — サーバーコンポーネント、クライアントコンポーネント、SSRのすべてに対応します。

既存のReactプロジェクトから移行する場合は、依存関係から**`react`と`react-dom`を削除**してください:

```sh
pnpm remove react react-dom
```

## 仕組み

`@lazarv/react-server`は`react`と`react-dom`を直接の**依存関係**（ピア依存関係ではなく）としてリストし、`react-server-dom-webpack`の代わりにバンドラー非依存のRSCシリアライゼーションレイヤーである`@lazarv/rsc`を使用しています。開発時とビルド時の両方で、ランタイムはモジュールエイリアスを設定し、あなたのコードやサードパーティライブラリからの`react`または`react-dom`の`import`がランタイムにバンドルされたReactバージョンに解決されるようにします。

このエイリアシングは、3つのVite環境すべてにおいてViteモジュール解決レベルで動作します:

- **`rsc`** — React Server Componentsは`react-server`エクスポート条件（`react.react-server.js`）を使用します
- **`ssr`** — サーバーサイドレンダリングは標準のReactエントリ（`index.js`）を使用します
- **`client`** — ブラウザのクライアントコンポーネントはViteによってバンドルされた同じReactバージョンを使用します

エイリアシングはバンドリングの前に解決をインターセプトするため、`react`や`react-dom`から`import`するサードパーティライブラリは、設定なしでランタイムのReactを透過的に使用します。

## サードパーティライブラリの互換性

ほとんどのReactライブラリは`@lazarv/react-server`ですぐに動作します。主な互換性の考慮事項は以下の通りです:

### シームレスに動作するライブラリ

標準的なインポートを通じて`react`や`react-dom`に依存するライブラリはすべて動作します。モジュールエイリアシングによりランタイムのReactが提供されるためです。これには以下が含まれます:

- **UIコンポーネントライブラリ** — [Material UI](/integrations/mui)、[Mantine](/integrations/mantine)、Chakra UI、Radix、shadcn/ui、Headless UIなど
- **状態管理** — Zustand、Jotai、Recoil、Redux（クライアントコンポーネント内で使用）
- **データフェッチ** — [TanStack Query](/integrations/react-query)、SWR、Apollo Client（クライアントコンポーネント内で使用）
- **アニメーション** — Framer Motion、React Spring
- **フォーム** — React Hook Form、Formik（クライアントコンポーネント内で使用）
- **スタイリング** — Emotion、Styled Components、Tailwind CSS、CSS Modules

### クライアントコンポーネントとサーバーコンポーネント

Reactフック（`useState`、`useEffect`、`useRef`など）やブラウザAPIを使用するサードパーティライブラリは、[クライアントコンポーネント](/guide/client-components)（`"use client"`ディレクティブを持つファイル）内で使用する必要があります。これは`@lazarv/react-server`の制限ではなく、React Server Componentsのルールです。

```jsx filename="./src/Counter.jsx"
"use client";

import { useState } from "react";
import { motion } from "framer-motion";

export default function Counter() {
  const [count, setCount] = useState(0);
  return (
    <motion.button
      whileTap={{ scale: 0.95 }}
      onClick={() => setCount(count + 1)}
    >
      count is {count}
    </motion.button>
  );
}
```

サーバーコンポーネントはクライアントコンポーネントをインポートしてレンダリングできますが、フックやブラウザAPIを直接使用することはできません。詳細については、[クライアントコンポーネントガイド](/guide/client-components)と[サーバーコンポーネントガイド](/guide/server-components)を参照してください。

### Reactバージョンチェックを行うライブラリ

一部のライブラリはランタイムでバージョンチェックを実行します（例：`React.version`の読み取り）。`@lazarv/react-server`は実験的なReactビルドを使用しているため、バージョン文字列は安定版の`19.x.x`ではなく`0.0.0-experimental-...`のようになります。ほとんどのライブラリはこれを適切に処理しますが、まれにバージョンを認識できないために警告を出したり、ロードを拒否するライブラリがあります。

このような場合でも、通常ライブラリは正しく動作します — 警告は安全に無視できます。ライブラリがバージョンで厳密にブロックする場合は、そのライブラリの新しいバージョンでバージョンチェックが緩和されていないか確認するか、ライブラリのメンテナーにissueを作成してください。

### 独自のReactをバンドルするライブラリ

まれに、ピア依存関係としてインポートする代わりに、独自のReactコピーをバンドルするライブラリがあります。これは「複数のReactインスタンス」問題を引き起こす可能性があります — フックエラー（`Invalid hook call`）やコンテキストが共有されないなどの症状が現れます。ただし、`@lazarv/react-server`は`react`と`react-dom`の重複排除を自動的に行うため、これらのケースのほとんどは追加の設定なしで処理されます。

## React Compiler

[React Compiler](https://react.dev/learn/react-compiler)は、Reactコンポーネントとフックを自動的にメモ化するオプトインのBabelプラグインです。コードをビルド時に解析し、キャッシュが必要な値に対して`useMemoCache`呼び出しを生成することで、`useMemo`、`useCallback`、`React.memo`の手動コードのほとんどを不要にします。

`@lazarv/react-server`は内部で`@vitejs/plugin-react`を使用してReactのBabel変換を適用しているため、React Compilerを有効化するには、`babel-plugin-react-compiler`を設定した独自の`@vitejs/plugin-react`インスタンスを提供するだけで済みます。設定内にユーザー指定の`vite:react`プラグインが検出されると、ランタイムは組み込みのものの代わりにあなたのプラグインを使用します — そのため、ランタイムのReactエイリアシング、JSX変換、Fast Refreshはこれまで通り動作します。

### インストール

```sh
pnpm add -D @vitejs/plugin-react babel-plugin-react-compiler
```

`react`や`react-dom`をインストールする必要は**ありません** — [package.jsonにReactは不要](#no-react-in-your-package-json)を参照してください。

### 設定

`react-server.config.mjs`に`@vitejs/plugin-react`と`babel-plugin-react-compiler`を追加します:

```js filename="./react-server.config.mjs"
import react from "@vitejs/plugin-react";

export default {
  plugins: [
    react({
      babel: {
        plugins: [
          [
            "babel-plugin-react-compiler",
            {
              target: "19",
            },
          ],
        ],
      },
    }),
  ],
};
```

`target: "19"`オプションは、`@lazarv/react-server`に同梱されているReactビルドがネイティブサポートするReact 19の組み込み`useMemoCache`フックへの呼び出しを生成するようReact Compilerに指示します。`react-compiler-runtime`ポリフィルは不要です。

### 動作確認

ビルド（`react-server build`）後、`.react-server/client/`内の生成されたクライアントコンポーネントのバンドルを確認してください。コンパイルされたコンポーネントには`c(N)`（`useMemoCache`キャッシュ）の呼び出しと`Symbol.for("react.memo_cache_sentinel")`によるスロット初期化が含まれます。これらが見つかればコンパイラが動作しています。

### コンパイルモード

デフォルトではReact Compilerは`infer`モードで動作し、安全にメモ化できると判断したすべてのコンポーネントをメモ化しようとします。代わりに選択的にオプトインしたい場合は、`compilationMode: "annotation"`を設定し、コンパイルしたいコンポーネントやフックに`"use memo"`ディレクティブを追加します:

```js filename="./react-server.config.mjs"
react({
  babel: {
    plugins: [
      [
        "babel-plugin-react-compiler",
        {
          target: "19",
          compilationMode: "annotation",
        },
      ],
    ],
  },
}),
```

```jsx filename="./Chart.jsx"
"use client";

function Chart({ data }) {
  "use memo";
  // …このコンポーネントだけがコンパイルされます。
}
```

### サーバーコンポーネントとクライアントコンポーネント

Babel変換は3つの環境（`rsc`、`ssr`、`client`）すべてで実行されるため、React Compilerはサーバーコンポーネントとクライアントコンポーネントの両方をコンパイルする可能性があります。再レンダリングのメモ化の恩恵を受けるのはブラウザ上のクライアントコンポーネントだけですが、SSR時にも同じ変換が走るためサーバーコンポーネントをコンパイルすることにも意味があります。特定のファイルをコンパイルから除外したい場合は、標準の`babel-plugin-react-compiler`オプション（`sources`フィルターまたは`"use no memo"`ディレクティブ）を使用してください。

サーバー関数（`"use server"`）に対してコンパイラはノーオペレーションです — Reactコンポーネントではないため、コンパイラは構造を見て無視します。

### サンプル

完全に動作する設定は[`react-compiler`サンプル](https://github.com/lazarv/react-server/tree/main/examples/react-compiler)で確認できます。

## TypeScript型定義

TypeScriptユーザーは、`tsconfig.json`で実験的なReact型定義を使用する必要があります:

```json filename="./tsconfig.json"
{
  "compilerOptions": {
    "types": ["react/experimental", "react-dom/experimental"]
  }
}
```

これにより、エディタが`"use client"`、`"use server"`、`useActionState`、`useFormStatus`などの最新React APIを認識するようになります。完全な設定例については、[TypeScript統合ガイド](/integrations/typescript)を参照してください。

## Reactバージョンの確認

`@lazarv/react-server`が使用しているReactバージョンを確認するには、ランタイムでチェックできます:

```jsx
import { version } from "react";

export default function Version() {
  return <p>React version: {version}</p>;
}
```

またはCLIでインストール済みバージョンを確認できます:

```sh
node -e "console.log(require('@lazarv/react-server/node_modules/react/package.json').version)"
```