第89章:React Compiler の未来
1️⃣ ここまでの世界:「メモ化」を手でがんばる時代 🧠
第81〜88章でやってきたこと、ちょっと思い出してみましょう👇
-
不要な再レンダリングを防ぐために…
React.memo(...)でコンポーネントを包むuseCallback(...)で関数をメモ化するuseMemo(...)で重い計算の結果をメモ化する
みたいな「手作業での最適化」をいっぱい書きましたよね 📝
この章は、そんな世界から
「もう、そういうの、コンパイラが自動でやっとくね〜」
という 新しい世界への入り口 です ✨
2️⃣ React Compiler ってなに?ざっくり一言で 💡
React Compiler は、React チーム公式の
🎯 「ビルド時にあなたのコードを読んで、 安全なところだけ自動でメモ化してくれるツール」
です。
- ビルド時(
npm run buildとかのタイミング)に動く - コンポーネントやフックのコードを解析して
useMemo/useCallback/React.memoみたいなことを 自動でいい感じにやってくれる✨(React)
しかも 2025年10月に v1.0 として安定版リリース されていて、 「実験用」から「本番OKなやつ」に昇格しています 🎉(React)
3️⃣ 図でイメージする:どこで動いてるの?🧩
React Compiler は、ブラウザの中ではなくて、 ビルドツール(Vite / Webpack など)の裏側で動きます。
「自分が書くコード」はこれまで通りだけど、 裏でコンパイラが “勝手に賢くしてくれる” というイメージです 😊
4️⃣ 具体的に何をしてくれるの?🧮
公式ドキュメントやブログをざっくりまとめると、React Compiler は:(React)
-
✅ 自動メモ化(Automatic Memoization)
- 入力(Props や State)が変わらないときは そのコンポーネントを 再レンダリングしない ようにする
-
✅ コンポーネント & フック両方を最適化
- コンポーネントだけじゃなくて、フックも解析してくれる
-
✅ データの流れと「変更される / されない」を解析
- 「この値は変わらない」「ここはミューテートしてない」 みたいな情報をもとに、安全にスキップできるか判断する
-
✅ 「これは危なそう…」なところは あえて最適化しない
- 無理にいじってバグらせるより、「触らない」を選んでくれる
5️⃣ React 19 と React Compiler の関係 👩💻💻
2024〜2025年で React まわりはけっこう大きく変わりました。
- React 19 系がリリースされて、 新しいデータ取得やフォーム機能、パフォーマンス改善などが入り…
- その中の “相棒” みたいな位置づけで 🌟 React Compiler が実用レベルに到達 しました。(WEQテクノロジーズ)
さらに今は:
- Next.js や Expo など、人気フレームワークにも React Compiler のサポートがどんどん入ってきている(Next.js)
- Vite + React でも、Babel プラグインを入れるだけで 簡単に使えるようになっています 🎯(React)
6️⃣ Before / After:手メモ化 → Compiler 任せの世界 ✂️✨
「実際のコードがどう変わるの?」というイメージを シンプルな例で見てみましょう 👀
🐢 Before:がんばって useMemo / useCallback / React.memo
// UserList.tsx
import { memo, useCallback, useMemo } from "react";
type User = {
id: number;
name: string;
};
type UserListProps = {
users: User[];
onSelect: (id: number) => void;
};
const UserListItem = memo(function UserListItem(props: {
user: User;
onSelect: (id: number) => void;
}) {
const { user, onSelect } = props;
console.log("render:", user.name);
return (
<li>
<button onClick={() => onSelect(user.id)}>{user.name}</button>
</li>
);
});
export function UserList({ users, onSelect }: UserListProps) {
const sortedUsers = useMemo(
() => [...users].sort((a, b) => a.name.localeCompare(b.name)),
[users]
);
const handleSelect = useCallback(
(id: number) => {
onSelect(id);
},
[onSelect]
);
return (
<ul>
{sortedUsers.map((user) => (
<UserListItem
key={user.id}
user={user}
onSelect={handleSelect}
/>
))}
</ul>
);
}
やってることは正しいけど…
- 型も Props も長い 🥹
useMemo/useCallbackの依存配列も気にしないといけない- ちょっとコードがゴチャっとしますよね。
🐇 After:React Compiler 前提だと、コードは素直でOK
React Compiler を有効化している前提なら、 まずは「読みやすい素直なコード」から書いてOK という世界観になります。(React)
// UserList.tsx
type User = {
id: number;
name: string;
};
type UserListProps = {
users: User[];
onSelect: (id: number) => void;
};
function UserListItem({ user, onSelect }: {
user: User;
onSelect: (id: number) => void;
}) {
console.log("render:", user.name);
return (
<li>
<button onClick={() => onSelect(user.id)}>
{user.name}
</button>
</li>
);
}
export function UserList({ users, onSelect }: UserListProps) {
// いったん「素直に」書く
const sortedUsers = [...users].sort((a, b) =>
a.name.localeCompare(b.name)
);
return (
<ul>
{sortedUsers.map((user) => (
<UserListItem
key={user.id}
user={user}
onSelect={onSelect}
/>
))}
</ul>
);
}
このコードを ビルドするときに React Compiler が解析して、
- どこをメモ化すればいいか
- どの再レンダリングをスキップできるか
を自動で判断してくれます 🤖✨
もちろん、本当にめちゃくちゃ重い処理 とかは
まだ useMemo を書いた方がわかりやすいケースもありますが、
「とりあえず全部 useCallback で囲んどこう…」みたいな世界からは
だいぶ解放されるイメージです 🎉
7️⃣ どうやって有効化するの?(Vite + React + TS の例)⚙️
※ このロードマップでは「概念」をメインにしますが、 「ちょっと試してみたい!」というとき用に、 Vite プロジェクトでのざっくり手順も書いておきます 🧪
① パッケージを入れる
VS Code のターミナルで(WindowsでもOK)👇
npm install -D babel-plugin-react-compiler
公式ドキュメントでも、babel-plugin-react-compiler を
devDependency として入れることが推奨されています。(React)
② vite.config.ts にプラグインを追加
// vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
export default defineConfig({
plugins: [
react({
babel: {
plugins: ["babel-plugin-react-compiler"],
},
}),
],
});
これで、
npm run dev→ 開発時からコンパイラの動きを試せるnpm run build→ 本番ビルド時にも最適化が走る
という感じになります 💻✨(React)
8️⃣ まだ「魔法」ではないポイントも大事 ⚠️
React Compiler はかなりすごいんですが、 何でもかんでも自動で最適にしてくれる“魔法”ではない です。
🔎 コンパイラが前提にしているルール
公式ブログなどでも、React Compiler が安全に動くためには、 React のルールを守って書かれていることが前提 だと説明されています。(React)
たとえば:
propsやstateを 直接書き換えない(イミュータブルに扱う)- コンポーネントは 同じ入力なら同じ出力(副作用のない純粋な関数)
- Hooks のルール(呼び出す順番を変えない etc.)を守る
これらをちゃんと守っているからこそ、
「このコンポーネントは入力が変わらないなら 結果も変わらないはずだから、再レンダリングいらないよね」
と コンパイラが自信を持って判断できる んですね ✨
🔦 どうしても困ったときの「オフスイッチ」
逆に、「この関数は今は最適化してほしくない!」 というときのために、
"use no memo"というディレクティブで その関数だけコンパイラから除外する 機能も用意されています。(React)
9️⃣ いまの私たちの立ち位置:どう意識しておけばいい?🧭
このロードマップの学習者的には、こんな感じで考えておくとラクです👇
-
まずは「ふつうにきれいな React コード」を書く力をつける
- State や Props の基本
- イミュータブルな更新
- Hooks のルール → これが コンパイラが活躍できる土台 💪
-
パフォーマンス最適化の「考え方」は学んでおく
- 「なぜ再レンダリングが問題になるのか」
- 「どこがボトルネックになりやすいか」 → これは React Compiler 時代でも超重要
-
実務では、
- まずは素直なコードを書く
- 必要に応じて React Compiler を導入
- それでも足りなければ
useMemo/useCallbackなどを ピンポイントで 追加
という流れが主流になっていきそうです 🌈
🔟 さらに安心材料:ESLint プラグインもあるよ ✅
React Compiler には ESLint プラグイン もあって、
- コンパイラをまだ使っていなくても
- 「React のルールを破ってないか?」をチェックしてくれる
という使い方ができます。 React チームも「全員使ってほしい」とおすすめしているので、 実案件ではかなり心強い相棒になりそうです 💪(React)
まとめ 🎀
この章で押さえておきたいポイントはこれ👇
-
React Compiler は ビルド時に動く「自動メモ化コンパイラ」 🤖
-
useMemo/useCallback/React.memoの多くを 裏側で肩代わり してくれるようになる ✨ -
でも、
- イミュータブルな更新
- Hooks のルール
- 純粋なコンポーネント設計 といった 基礎力がないとコンパイラも本気を出せない
-
Vite + React + TS でも、Babel プラグインを足すだけで 比較的カンタンに試せる 🛠️
-
これからの React は
「まずはきれいで素直なコードを書く → あとはコンパイラと一緒に最適化していく」 という時代になっていきます 🚀
チェックタイム ✏️(軽く答えを考えてみてね)
Q1. React Compiler は「いつ」動くツールでしょう? Q2. React Compiler が特に自動化してくれるのはどんな処理? Q3. React Compiler にとってうれしい「書き方のルール」を 2 つ思い出してみてください。
(例:state を直接書き換えない、Hooks のルールを守る、など)
この章では「未来の React の姿」をちらっと覗きました 👀✨ 次の章では、「メモ化はあくまで最適化テクニックであって、 まずは正しく動くものを作るのが大事だよね」という話に続いていきます 💖