React Compiler 是一个构建时工具,它能自动优化您的 React 应用,消除手动进行记忆化(memoization)的繁琐工作。
一、为什么需要 React Compiler?
尽管 React 本身性能出色,但在复杂应用中,我们仍需要手动使用 useMemo、useCallback 和 React.memo 来缓存组件和值,以保持应用的响应速度。这种手动优化不仅繁琐、容易出错,还会增加代码的维护成本。
手动记忆化的常见痛点
下面是一个手动记忆化存在细微 Bug 的典型例子:

<Item key={item.id} onClick={() => handleClick(item)} />
在这段代码中,即使 handleClick 函数被 useCallback 包裹,但每次渲染时,箭头函数 () => handleClick(item) 都会创建一个全新的函数引用。这将导致 Item 组件每次都会接收到一个新的 onClick prop,从而破坏了其自身的记忆化效果,引发不必要的重新渲染。这类问题在复杂的JavaScript应用中尤其常见。
自动优化带来的改变
使用 React Compiler 后,您可以编写最直观的代码,而编译器会在幕后自动为您完成所有记忆化工作。

编译器能够智能地分析代码依赖,自动插入必要的缓存逻辑,确保组件只在其依赖发生变化时才会重新渲染。
二、安装与基础配置
前提条件
React Compiler 主要为 React 19 设计,同时也兼容 React 17 和 18。您需要在插件配置中通过 target 属性指定对应的 React 版本。
- React 19: 使用内置的
react/compiler-runtime。
- React 17/18: 需要额外安装
react-compiler-runtime 包。
配置示例:
{ target: ‘19’ // 或 ‘18’、‘17’ }
安装步骤
-
安装 Babel 插件
通过包管理器安装编译器插件:
pnpm install -D babel-plugin-react-compiler@latest
-
配置 Babel
关键点:React Compiler 必须在您的 Babel 插件管道中首先运行。这是因为编译器需要原始的源代码信息来进行正确分析。
module.exports = {
plugins: [
‘babel-plugin-react-compiler’, // 必须首先运行!
// … 其他插件
],
// … 其他配置
};
-
集成 ESLint 支持(推荐)
React Compiler 提供了一条 ESLint 规则,用于帮助识别编译器无法优化的代码模式。当规则报错时,意味着对应的组件或 Hook 将被跳过优化(这是安全的,不会影响其他部分的优化)。
安装命令:
npm install -D eslint-plugin-react-hooks@latest
您可以根据自己的节奏逐步修复这些警告,从而逐步提升应用的优化覆盖率。这属于前端工程化中提升代码质量的重要一环。
验证优化效果
- 检查 React DevTools:被优化的组件会在 React DevTools 中显示一个 “Memo ✨” 徽章。
- 检查构建输出:编译后的代码将包含编译器自动添加的记忆化逻辑。
故障排查
如果某个组件在编译后出现问题,可以使用 “use no memo” 指令将其暂时排除在优化范围之外。
function ProblematicComponent() {
“use no memo”;
// 这里是组件代码
}
三、插件配置项详解
您可以通过配置项精细控制 React Compiler 的行为。
1. 编译控制 (compilationMode)
此选项用于控制编译器选择哪些函数进行编译的策略。

{ compilationMode: ‘infer’ // 可选 ‘annotation’、‘syntax’、‘all’ }
‘infer’ (默认):编译器使用启发式方法智能识别:
- 使用
“use memo” 指令明确注释的函数。
- 命名符合组件(帕斯卡命名法)或 Hook(
use 前缀)规范,并且创建了 JSX 或调用了其他 Hook 的函数。
‘annotation’:仅编译被 “use memo” 指令明确标记的函数。适合用于增量式迁移。
‘syntax’:仅编译使用 Flow 的 component 和 hook 语法声明的组件和 Hook。注意:此模式无法与 TypeScript 一起使用。
‘all’:编译所有顶层函数。不推荐,因为它可能错误地编译非 React 函数。
无论在哪种模式下,带有 “use no memo” 指令的函数总是会被跳过。
2. 版本兼容性 (target)
此选项确保编译器生成的代码与您项目中使用的 React 版本兼容。

3. 错误处理 (panicThreshold)
控制编译器如何处理违反 React 规则的代码,决定是让构建失败还是跳过问题组件。

‘none’ (默认,推荐):跳过无法编译的组件,继续构建过程。
‘critical_errors’:仅在发生关键编译器错误时使构建失败。
‘all_errors’:遇到任何编译诊断信息都立即使构建失败。
4. 调试日志 (logger)
提供一个自定义日志功能,用于记录编译过程中的各种事件,便于调试。

核心方法:
logEvent:传入文件名和事件详情来记录每次编译器事件。
事件类型:
CompileSuccess:函数成功编译。
CompileError:因错误而跳过函数。
CompileDiagnostic:非致命的诊断信息。
CompileSkip:因其他原因跳过函数。
PipelineError:意外的编译管线错误。
Timing:性能计时信息。
启用日志后,您可以获得非常详细的错误信息,帮助定位问题。

5. 特性开关 (gating)
此选项用于启用条件编译,允许您通过运行时的特性开关(Feature Flag)来控制是否使用优化后的代码,非常适合用于 A/B 测试或渐进式发布。

配置项:
source:特性开关模块的导入路径。
importSpecifierName:要导入的导出函数名称。
注意事项:
- gating 函数必须返回一个布尔值。
- 同时包含编译版本和原始版本会增加最终的包体积。
- 所有包含已编译函数的文件都会被添加该导入。
使用流程:
-
创建一个特性开关模块:

// featureFlags.js
export function isReactCompilerEnabled() {
return window.enableReactCompiler === true;
}
-
在 Babel 配置中启用 gating:

{
plugins: [
[‘babel-plugin-react-compiler’, {
gating: {
source: ‘./featureFlags’,
importSpecifierName: ‘isReactCompilerEnabled’
}
}]
]
}
-
编译器将生成条件编译的代码:

重要提示:gating 函数在模块加载时仅执行一次,因此一旦 JavaScript 包被解析执行,本次浏览器会话中组件的优化状态就将保持不变。
四、编译指令
React Compiler 指令是一种特殊的字符串字面量,用于在代码层面控制特定函数是否被编译。

可用指令
“use memo”:强制函数参与编译。在 annotation 模式下必须使用,或在 infer 模式下覆盖默认推断逻辑。
“use no memo”:阻止函数被编译。用于调试问题或处理不兼容的代码。
作用范围
-
函数级别:指令仅影响其所在的函数。

function MyComponent() {
“use memo”; // 此组件将被优化
// …
}
-
模块级别:将指令放在模块顶部,可以影响该模块内所有符合编译条件的函数。

“use memo”; // 此文件中的所有组件和Hook都将被优化
// 模块内的函数定义…