title: React category: Integrations order: 3
import Link from "../../../../components/Link.jsx";
React
@lazarv/react-serverにはReactが組み込まれています。reactやreact-domを自分でインストールする必要はありません — ランタイムにはReact Server Components、サーバーアクション、およびすべての最新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インスタンス」バグ(フックの破損、コンテキストの破損など)を回避します。
@lazarv/react-serverでプロジェクトを作成する場合、package.jsonにreactやreact-domを依存関係として記載するべきではありません:
{
"dependencies": {
"@lazarv/react-server": "latest"
}
}
これだけです。ランタイムがプロジェクト全体にReactを提供します — サーバーコンポーネント、クライアントコンポーネント、SSRのすべてに対応します。
既存のReactプロジェクトから移行する場合は、依存関係から**reactとreact-domを削除**してください:
pnpm remove react react-dom
<Link name="how-it-works">
## 仕組み
</Link>@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、Mantine、Chakra UI、Radix、shadcn/ui、Headless UIなど
- 状態管理 — Zustand、Jotai、Recoil、Redux(クライアントコンポーネント内で使用)
- データフェッチ — TanStack Query、SWR、Apollo Client(クライアントコンポーネント内で使用)
- アニメーション — Framer Motion、React Spring
- フォーム — React Hook Form、Formik(クライアントコンポーネント内で使用)
- スタイリング — Emotion、Styled Components、Tailwind CSS、CSS Modules
クライアントコンポーネントとサーバーコンポーネント
Reactフック(useState、useEffect、useRefなど)やブラウザAPIを使用するサードパーティライブラリは、クライアントコンポーネント("use client"ディレクティブを持つファイル)内で使用する必要があります。これは@lazarv/react-serverの制限ではなく、React Server Componentsのルールです。
"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を直接使用することはできません。詳細については、クライアントコンポーネントガイドとサーバーコンポーネントガイドを参照してください。
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コンポーネントとフックを自動的にメモ化するオプトインの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はこれまで通り動作します。
インストール
pnpm add -D @vitejs/plugin-react babel-plugin-react-compiler
reactやreact-domをインストールする必要はありません — package.jsonにReactは不要を参照してください。
設定
react-server.config.mjsに@vitejs/plugin-reactとbabel-plugin-react-compilerを追加します:
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"ディレクティブを追加します:
react({
babel: {
plugins: [
[
"babel-plugin-react-compiler",
{
target: "19",
compilationMode: "annotation",
},
],
],
},
}),
"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サンプルで確認できます。
TypeScriptユーザーは、tsconfig.jsonで実験的なReact型定義を使用する必要があります:
{
"compilerOptions": {
"types": ["react/experimental", "react-dom/experimental"]
}
}
これにより、エディタが"use client"、"use server"、useActionState、useFormStatusなどの最新React APIを認識するようになります。完全な設定例については、TypeScript統合ガイドを参照してください。
@lazarv/react-serverが使用しているReactバージョンを確認するには、ランタイムでチェックできます:
import { version } from "react";
export default function Version() {
return <p>React version: {version}</p>;
}
またはCLIでインストール済みバージョンを確認できます:
node -e "console.log(require('@lazarv/react-server/node_modules/react/package.json').version)"