第4回
React Compiler 1.0:Viteへの導入とメモ化の確認方法
安定版になったReact Compilerを実際に試す。Vite 8環境への導入からDevToolsでの効果確認、既存のuseMemoとの付き合い方までを動かしながら解説する。
制作・運営:React Guide 運営者
教材の範囲:以下は別プロジェクトで試す手順とコード例です。記事内の見本は静的な説明用表示です。導入先のフレームワーク・外部サービスまでの実行確認は含めていません。
「React最新ラボ」第4回。今回はReactチーム公式の React Compiler 1.0 を、このサイトと同じ Vite 環境に入れて効果を確かめる。
React Compilerは何をするのか
React Compilerはビルド時にコンポーネントのコードを解析して、自動でメモ化コードに変換するBabelプラグインだ。コンパイル段階で変換し、生成コードはReactのランタイム機能を利用する。書くコードはプレーンなままでいい。
| 手書きメモ化(これまで) | React Compiler | |
|---|---|---|
| 書くもの | useMemo / useCallback / React.memo を自分で配置 |
何も書かない(プレーンなコード) |
| 抜け漏れ | 人間の判断次第。入れ忘れ・入れすぎが起きる | コンパイラが一律に解析 |
| メモ化の依存配列 | useMemo・useCallbackで管理 | 自動メモ化では手書きを減らせる。useEffectの依存配列は引き続き必要 |
| 対応バージョン | ─ | React 19推奨(17/18はランタイムパッケージ追加で可) |
導入する(Vite 8 + plugin-react v6 構成)
このサイトと同じ Vite 8 + @vitejs/plugin-react v6 の構成で入れてみる。v6からプラグイン内部のBabelが廃止されてRust製の変換(oxc)になったため、Babelプラグインである React Compiler は @rolldown/plugin-babel を別途足して動かす形になる。
npm i -D @rolldown/plugin-babel babel-plugin-react-compiler// vite.config.ts
import { defineConfig } from 'vite'
import react, { reactCompilerPreset } from '@vitejs/plugin-react'
import babel from '@rolldown/plugin-babel'
export default defineConfig({
plugins: [
react(),
babel({
presets: [reactCompilerPreset()],
}),
],
})reactCompilerPreset() は @vitejs/plugin-react が用意している設定済みプリセットで、babel-plugin-react-compiler を適切なデフォルトで組み込んでくれる。
Vite 7以前(plugin-react v5以前)なら従来どおり
react({ babel: { plugins: ['babel-plugin-react-compiler'] } })の1行で有効化できる。
効果を確かめる
わざと「親が更新されると子が巻き添えで再レンダリングされる」構成を作る。
// ./src/App.tsx
import { useState } from 'react'
import { HeavyList } from './HeavyList'
export default function App() {
const [count, setCount] = useState(0)
return (
<main>
<button onClick={() => setCount((c) => c + 1)}>カウント: {count}</button>
{/* count と無関係なのに、毎回再レンダリングされていた子 */}
<HeavyList items={['React', 'Vite', 'Tailwind']} />
</main>
)
}// ./src/HeavyList.tsx
export function HeavyList({ items }: { items: string[] }) {
console.log('HeavyList rendered')
return (
<ul>
{items.map((item) => (
<li key={item}>{item}</li>
))}
</ul>
)
}最適化が適用されれば、親の更新で子まで毎回実行する処理を省略できる場合がある。ただし、下の回数は仕組みを説明するための模式例で、実測値ではない。開発時のStrictMode、コンパイラがそのコードを処理できるか、propsの変化によって実際の回数は変わる。ログの回数だけで成功を断定せず、DevToolsとビルド出力を併せて確認する。
コンパイラなし
App:11回
HeavyList:11回(毎回巻き添え)
コンパイラあり
App:11回
HeavyList:1回(propsが同じなのでスキップ)
もう一つの確認方法が React DevTools。Componentsタブでコンパイル済みコンポーネントには 「Memo ✨」バッジが付く。バッジが見えない場合は、DevToolsの対応版、ビルド設定、除外指定、診断ログを確認する。
コンパイラが効かないとき:Rules of React
だから導入とセットで、リンタも最新にしておく。eslint-plugin-react-hooks の最新版にはコンパイラと同じ解析エンジンによるルールが入っていて、「なぜこのコンポーネントが最適化されないのか」を教えてくれる。
npm i -D eslint-plugin-react-hooks@latestまた、特定のコンポーネントだけコンパイラから除外したいときは、関数の先頭に "use no memo" ディレクティブを書く逃げ道もある。
function ProblemChild() {
'use no memo' // このコンポーネントはコンパイラの対象外にする
// ...
}既存の useMemo / useCallback は消すべき?
すぐに全部消す必要はない。コンパイラは手書きのメモ化と共存できるので、推奨の進め方はこうなる。
- まずコンパイラを有効化する(既存コードはそのまま)
- DevToolsとリンタで、最適化が効いているのを確認する
- 新しいコードからメモ化を手書きしない習慣に切り替える
- 既存のラップは、触るついでに少しずつ剥がす
つまずきやすい所
- 効果が見えない:もともと再レンダリングが問題になっていないアプリでは体感差は出ない。DevToolsの「Memo ✨」バッジとコンソールのレンダリング回数で確認する
- 一部だけバッジが付かない:設定・対象範囲・対応状況も含めて調べる。リンタの警告を確認する
- plugin-react v6でbabelオプションが効かない:v6でBabel内蔵が廃止されたため。この記事の
@rolldown/plugin-babel構成に切り替える
まとめ
- React Compiler 1.0はビルド時の自動メモ化。手書きのメモ化を減らせる場合がある
- Vite 8 + plugin-react v6では
@rolldown/plugin-babel+reactCompilerPreset()で有効化する - 効果はDevToolsの「Memo ✨」バッジとレンダリング回数で確認する
- 前提はRules of React。最適化されない理由を調べるため、
eslint-plugin-react-hooks最新版を併用する
次回は、React 19.2で安定版になった <Activity> と useEffectEvent を試す。「タブを切り替えても入力が消えないUI」と「useEffectの依存配列の悩み」を一気に解決する2つだ。
訂正と参照資料
2026-09-09:Vite設定のBabelプラグインのimport、プリセットの指定、プラグイン配列を公式の導入例に合わせて訂正しました。「依存配列が不要」は自動メモ化の範囲に限定し、固定のレンダリング回数は実測値ではないことを明記しました。ここでの訂正は公式仕様との照合であり、記事中の全サンプルを別プロジェクトで実行検証した記録ではありません。
確認してみる
同じ操作で導入前後を測る。Memoバッジだけで高速化とは判断せず、propsが変わる場合にも正しい結果が出るか確認する。
同じテーマの教材
useTransitionとuseDeferredValue:入力と一覧の更新を分ける
検索入力と一覧の更新を分けるサンプルでuseTransitionとuseDeferredValueを解説します。更新の優先度、memoとの関係、別スレッドや通信の間引きとの違いを確認します。
useCallbackで関数をメモ化:React.memoと組み合わせた最適化
ReactのuseCallbackを解説します。関数のメモ化・React.memoとの組み合わせ・useEffectの依存配列での活用を実例で解説。useMemoとの違いと使い分けも明確にします。
useMemoでパフォーマンス最適化:重い計算をメモ化する
ReactのuseMemoを解説します。メモ化の仕組み・高コスト計算の最適化・参照の安定化、そしてuseMemoを使うべき場面・使わなくてよい場面の判断基準を実例付きで学べます。