📋 目錄
你有多少時間花在
useMemo、useCallback、React.memo這些記憶化工具上?React Compiler(代號 React Forget)會幫你自動做這件事——在你寫 JSX 的時候,編譯器就幫你加上該加的 memo,輸出最佳化的 JavaScript。這不再是實驗品,v1.0 已經穩定。
前言:React Compiler 是什麼?
React 的效能瓶頸有 80% 來自不必要的重新 render。為了解決這個問題,開發者習慣手動加上 useMemo、useCallback、React.memo——但這些 API 很容易用錯或過度使用,而且讓程式碼膨脹。
React Compiler 的想法很直接:在編譯時期分析元件的資料流,自動決定哪些地方需要 memo。你繼續用原本的 React 寫法,編譯器幫你優化。
它的核心原理是 React Compiler 是一個 Babel Plugin(叫做 babel-plugin-react-compiler),它會分析 JSX 和 Hook 的語義,找出哪些值在某個範圍內是穩定的,並在輸出時自動加上對應的優化。
安裝與配置
Babel 專案
npm install -D babel-plugin-react-compiler
// babel.config.js
module.exports = {
plugins: [
['babel-plugin-react-compiler', {
// 生產環境才啟用編譯
target: '19',
// 建議打開這個,方便除錯
debugBehavior: true,
}],
],
};
Vite 專案
npm install -D babel-plugin-react-compiler
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [
react({
// babel plugin 會被 @vitejs/plugin-react 自動使用
babel: {
plugins: ['babel-plugin-react-compiler'],
},
}),
],
});
Next.js 專案(App Router)
npm install -D babel-plugin-react-compiler
// next.config.js
module.exports = {
experimental: {
// Next.js 15+ 內建支援 reactCompiler: true
reactCompiler: true,
},
};
如果是較舊的 Next.js 版本,可以在 babel.config.js 加入 plugin。
使用方式:不需要再手動 memo 了
這是 React Compiler 最重要的改變:大多數情況下,你不需要再手動 useMemo 和 useCallback。
Before(React Compiler 之前)
import React, { useState, useMemo, useCallback } from 'react';
// 手動處處 memo,程式碼膨脹
function ProductList({ products, filterText }: { products: Product[]; filterText: string }) {
const filteredProducts = useMemo(
() => products.filter(p => p.name.includes(filterText)),
[products, filterText]
);
const handleClick = useCallback((id: string) => {
console.log('clicked', id);
}, []);
return (
<ul>
{filteredProducts.map(product => (
<ProductItem
key={product.id}
product={product}
onClick={handleClick}
/>
))}
</ul>
);
}
After(React Compiler 之後)
// React Compiler 自動幫你做 memo
function ProductList({ products, filterText }: { products: Product[]; filterText: string }) {
const filteredProducts = products.filter(p => p.name.includes(filterText));
const handleClick = (id: string) => {
console.log('clicked', id);
};
return (
<ul>
{filteredProducts.map(product => (
<ProductItem
key={product.id}
product={product}
onClick={handleClick}
/>
))}
</ul>
);
}
注意:useMemo 和 useCallback 的 import 拿掉了,程式碼乾淨很多。編譯器會分析 filteredProducts 和 handleClick 的穩定性,自動加上對應的優化。
React Compiler 會對哪些東西自動優化?
編譯器會自動優化以下場景:
- Component:如果 Props 沒變,不重新 render
- Hooks 的回傳值:useState、useRef 等
- useMemo/useCallback:這些你還是可以寫,但 Compiler 會幫你檢查是否真的需要
- Context:如果 value 沒變,不觸發 consumer re-render
哪些不會被優化?
- 沒有穩定 Identity 的函式:如果一個函式的行為每次都不同(隨機值、外部依賴),Compiler 不會優化
- 被標注為
use noMemo的範圍:Compiler 會跳過這段程式碼
停用指令:Compiler 跳過特定區塊
如果某段程式碼 Compiler 優化會造成問題,可以用 use noMemo 跳過:
function Component({ items }: { items: Item[] }) {
'use noMemo';
// 這裡的程式碼不受 Compiler 控制
const processed = heavyComputation(items);
return <div>{processed}</div>;
}
或用 use memo 強制 Compiler 優化特定區塊:
function Component({ data }: { data: Data }) {
const summary = React.use('use memo', () => {
// 強迫這段用 memo 包起來
return computeSummary(data);
});
return <ExpensiveChart data={summary} />;
}
遷移須知
1. 先在一個小型元件上測試
不要一次對整個大型專案啟用 Compiler。先選一個 Render 頻率高的元件,加上 Compiler,觀察行為是否一致。
2. TypeScript 嚴格模式
React Compiler 需要準確的型別資訊來做資料流分析。確保 tsconfig.json 開啟 strict: true,否則 Compiler 可能誤判。
3. ESLint Plugin
React Compiler 有對應的 ESLint Plugin,能在開發時就警告你「這段程式碼可能讓 Compiler 失效」:
npm install -D eslint-plugin-react-compiler
// .eslintrc
{
"plugins": ["react-compiler"],
"rules": {
"react-compiler/react-compiler": "error"
}
}
4. 逐步啟用
Compiler 支援 compilerOptions.sources 讓你指定要編譯的檔案範圍,不必一次對整個 node_modules 生效。
實際效能測試
React Compiler 的效果取決於你的元件結構。以下是典型場景的改善幅度(根據 Meta 內部數據):
| 場景 | 改善幅度 |
|---|---|
| 列表 + 父子元件傳遞 Callback | 40-60% 減少 re-render |
| Context Provider 嵌套 | 30-50% 減少 re-render |
| 簡單靜態頁面 | 無明顯改善(正常,沒什麼要優化的) |
常見問題
Q:React Compiler 和 memo、useMemo 是什麼關係?
A:Compiler 在編譯時幫你自動加上相當於 memo 的優化。你不需要自己寫,但如果你寫了,Compiler 會尊重它——不會覆蓋你的決定。
Q:React Compiler 支援 Vue 或其他框架嗎?
A:目前只有 React。Compiler 依賴 React 的語義和 Hooks 模型,理論上可以移植到其他框架,但目前沒有計畫。
Q:Svelte 或 Solid 有類似工具嗎?
A:Svelte 和 Solid 因為編譯模型不同(直接編譯成 vanilla JS,沒有 virtual DOM),在編譯時就能做很多優化,不需要類似 Compiler 的工具。
Q:React Compiler v1.0 的最低 React 版本?
A:React 18.3 以上。建議使用 React 19 獲得完整支援。
Q:Compiler 會讓 bundle 變大嗎?
A:恰恰相反——Compiler 的輸出通常比手動寫的 memo 更精準,bundle 可能反而變小。
總結:React 開發的未來是更少 boilerplate
React Compiler v1.0 的核心價值:讓 React 開發者不需要再手動處理記憶化,把這個繁瑣的優化工作交給編譯器。
這篇文章涵蓋:
- React Compiler 的原理(Babel Plugin + 資料流分析)
- Babel、Vite、Next.js 的安裝方式
- 使用方式:不再需要 useMemo / useCallback
- 停用指令(
use noMemo) - 遷移建議(先小範圍測試、ESLint Plugin)
下一步:在你的 React 專案選一個小範圍(3-5 個元件),安裝並啟用 React Compiler,觀察編譯輸出差異。從簡單的列表頁開始,體驗「刪掉 useMemo 後反而變快」的感覺。