知海

React 编译器 v1.0 发布

React博客-新闻

React 编译器 v1.0 发布

2025年10月7日 作者:Lauren TanJoe SavonaMofei Zhang

React 团队很高兴与大家分享以下新更新:

  1. React Compiler 1.0 今日正式发布。
  2. 编译器驱动的 lint 规则已随 eslint-plugin-react-hooksrecommendedrecommended-latest 预设一同发布。
  3. 我们发布了一份增量采用指南,并与 Expo、Vite 和 Next.js 合作,使新应用能够在启用编译器的情况下创建。

今天,我们发布了编译器的第一个稳定版本。React Compiler 在 React 和 React Native 上都能运行,无需重写代码即可自动优化组件和 Hook。该编译器已在 Meta 的大型应用中得到充分测试,完全可用于生产环境。

React 编译器 是一个构建时工具,通过自动记忆化来优化你的 React 应用。去年,我们发布了 React Compiler 的首个测试版,并收到了许多宝贵的反馈和贡献。我们看到采用编译器的用户取得了显著成果,感到非常振奋(参见 Sanity StudioWakelet 的案例研究),并期待将编译器带给 React 社区中的更多用户。

这一版本的发布是近十年巨大而复杂的工程努力的结晶。React 团队对编译器的首次探索始于 2017 年的 Prepack 项目。虽然该项目最终被关闭,但团队从中获得了许多经验,为 Hooks 的设计提供了参考,而 Hooks 的设计本身也考虑到了未来的编译器。2021 年,黄玄 演示了 React Compiler 新尝试的首个迭代版本

尽管这个新 React Compiler 的首个版本最终被重写,但第一个原型让我们更有信心,认为这是一个可解决的问题,并且让我们认识到,另一种编译器架构可以精确地提供我们想要的记忆化特性。Joe SavonaSathya GunasekaranMofei ZhangLauren Tan 完成了我们的首次重写,将编译器架构迁移到基于控制流图(CFG)的高级中间表示(HIR)。这为 React Compiler 中更精确的分析乃至类型推断铺平了道路。此后,编译器的许多重要部分都被重写,每一次重写都吸取了前一次尝试的经验。同时,我们得到了 React 团队 许多成员的大力帮助和贡献。

这个稳定版本是我们众多版本中的第一个。编译器将继续演进和改进,我们期待它成为 React 未来十年甚至更长时间的新基础和新时代。

你可以直接前往快速上手阅读,或者继续阅读 React Conf 2025 的精彩内容。

React Compiler 是如何工作的?

React Compiler 是一个优化编译器,通过自动记忆化来优化组件和 Hook。目前,它实现为一个 Babel 插件,但在很大程度上与 Babel 解耦,它将 Babel 提供的抽象语法树(AST)降级为其自创的 HIR,并通过多个编译器遍,仔细理解 React 代码的数据流和可变性。这使得编译器能够对渲染中使用的值进行细粒度的记忆化,包括能够有条件地进行记忆化,而这是手动记忆化无法实现的。

js {8} 复制代码
import { use } from 'react';

export default function ThemeProvider(props) {
  if (!props.children) {
    return null;
  }
  // The compiler can still memoize code after a conditional return
  const theme = mergeTheme(props.theme, use(ThemeContext));
  return (
    <ThemeContext value={theme}>
      {props.children}
    </ThemeContext>
  );
}

React Compiler Playground 中查看此示例。

除了自动记忆化,React Compiler 还有在 React 代码上运行的验证遍。这些验证遍对 React 规则 进行编码,并利用编译器对数据流和可变性的理解,在违反 React 规则的地方提供诊断。这些诊断通常会暴露隐藏在 React 代码中的潜在错误,并且主要通过 eslint-plugin-react-hooks 显示。

要了解更多关于编译器如何优化代码的信息,请访问 Playground

立即使用 React Compiler

要安装编译器:

npm

bash 复制代码
npm install --save-dev --save-exact babel-plugin-react-compiler@latest

pnpm

bash 复制代码
pnpm add --save-dev --save-exact babel-plugin-react-compiler@latest

yarn

bash 复制代码
yarn add --dev --exact babel-plugin-react-compiler@latest

作为稳定版发布的一部分,我们一直在让 React Compiler 更容易添加到你的项目中,并优化了编译器生成记忆化的方式。React Compiler 现在支持将可选链和数组索引作为依赖。这些改进最终会减少重新渲染,让 UI 响应更快,同时让你能够继续编写惯用的声明式代码。

你可以在我们的文档中找到使用编译器的更多详细信息。

我们在生产环境中看到的效果

编译器已应用于 Meta Quest Store 等应用。我们看到初始加载和跨页面导航性能提升了最高 12%,某些交互的速度提升了 2.5 倍以上。即便在这些提升下,内存占用保持稳定。尽管你的情况可能有所不同,我们建议在你的应用中尝试使用编译器,以观察类似的性能提升。

向后兼容性

正如测试版公告中所述,React Compiler 与 React 17 及以上版本兼容。如果你尚未使用 React 19,你可以通过在编译器配置中指定最低目标版本,并将 react-compiler-runtime 添加为依赖来使用 React Compiler。相关文档见这里

通过编译器驱动的 lint 强制实施 React 规则

React Compiler 包含一个 ESLint 规则,帮助识别违反 React 规则 的代码。该 linter 不需要安装编译器,因此升级 eslint-plugin-react-hooks 没有风险。我们建议所有人立即升级。

如果你已经安装了 eslint-plugin-react-compiler,现在可以移除它,改用 eslint-plugin-react-hooks@latest。非常感谢 @michaelfaith 为这项改进做出的贡献!

要安装:

npm

bash 复制代码
npm install --save-dev eslint-plugin-react-hooks@latest

pnpm

bash 复制代码
pnpm add --save-dev eslint-plugin-react-hooks@latest

yarn

bash 复制代码
yarn add --dev eslint-plugin-react-hooks@latest
js {6} 复制代码
// eslint.config.js (Flat Config)
import reactHooks from 'eslint-plugin-react-hooks';
import { defineConfig } from 'eslint/config';

export default defineConfig([
  reactHooks.configs.flat.recommended,
]);
js {3} 复制代码
// eslintrc.json (Legacy Config)
{
  "extends": ["plugin:react-hooks/recommended"],
  // ...
}

要启用 React Compiler 规则,我们建议使用 recommended 预设。你也可以查看 README 获取更多说明。以下是我们曾在 React Conf 上展示的几个示例:

我应该如何处理 useMemo、useCallback 和 React.memo?

默认情况下,React Compiler 会根据其分析和启发式方法对你的代码进行记忆化。在大多数情况下,这种记忆化将与你手写的效果一样精确,甚至更精确——如前所述,编译器甚至可以在 useMemo/useCallback 无法使用的场景下进行记忆化,例如在提前返回之后。

然而,在某些情况下,开发者可能需要对记忆化有更多控制。useMemouseCallback 这两个 Hook 可以继续与 React Compiler 一起使用,作为一种逃生舱,用于控制哪些值被记忆化。一个常见的使用场景是,当某个被记忆化的值被用作 effect 的依赖时,以确保 effect 不会在其依赖没有实质变化时重复触发。

对于新代码,我们建议依赖编译器进行记忆化,并在需要精确控制时使用 useMemo/useCallback

对于现有代码,我们建议要么保留现有的记忆化(移除它可能会改变编译输出),要么在移除记忆化之前进行仔细测试。

新应用应使用 React Compiler

我们已与 Expo、Vite 和 Next.js 团队合作,将编译器集成到新应用创建体验中。

Expo SDK 54 及以上版本默认启用编译器,因此新应用从一开始就能自动利用编译器。

bash 复制代码
npx create-expo-app@latest

ViteNext.js 用户可以在 create-vitecreate-next-app 中选择启用了编译器的模板。

bash 复制代码
npm create vite@latest
bash 复制代码
npx create-next-app@latest

增量采用 React Compiler

如果你正在维护现有应用,可以按自己的节奏部署编译器。我们发布了一份分步的增量采用指南,涵盖门控策略、兼容性检查和部署工具,让你能够放心地启用编译器。

swc 支持(实验性)

React Compiler 可以安装在多种构建工具中,如 Babel、Vite 和 Rsbuild。

除了这些工具,我们一直在与 swc 团队的 Kang Dongyoon(@kdy1dev)合作,为 React Compiler 添加 swc 插件支持。虽然这项工作尚未完成,但在你的 Next.js 应用中启用 React Compiler 后,Next.js 的构建性能现在应该会有显著提升。

我们建议使用 Next.js 15.3.1 或更高版本,以获得最佳的构建性能。

Vite 用户可以继续使用 vite-plugin-react 通过将其添加为 Babel 插件 来启用编译器。我们还在与 oxc 团队合作,为编译器添加支持。一旦 rolldown 正式发布并在 Vite 中得到支持,并且 oxc 支持 React Compiler,我们将更新文档提供迁移说明。

升级 React Compiler

当自动记忆化严格用于性能优化时,React Compiler 的效果最佳。未来版本的编译器可能会改变记忆化的应用方式,例如,它可能会变得更细粒度、更精确。

然而,由于产品代码有时会以 JavaScript 中无法静态检测的方式违反 React 规则,改变记忆化偶尔会产生意外结果。例如,一个先前被记忆化的值可能被用作组件树中某个 useEffect 的依赖。改变该值的记忆化方式或是否记忆化,可能导致该 useEffect 过度触发或触发不足。虽然我们鼓励仅在需要同步时使用 useEffect,但你的代码库中可能存在覆盖其他用例的 useEffect,例如需要在特定值变化时才会运行的 effects。

换句话说,改变记忆化在极少数情况下可能导致意外行为。因此,我们建议遵循 React 规则,并对应用进行持续的端到端测试,这样你就可以放心地升级编译器,并识别可能导致问题的任何违反 React 规则的行为。

如果你的测试覆盖率不佳,我们建议将编译器固定到精确版本(如 1.0.0),而不是使用 SemVer 范围(如 ^1.0.0)。你可以通过在升级编译器时传入 --save-exact(npm/pnpm)或 --exact(yarn)标志来实现。然后,你应该手动升级编译器,并注意检查应用是否仍然按预期工作。


感谢 Jason BontaJimmy LaiKang Dongyoon(@kdy1dev)和 Dan Abramov 对本文的审阅和编辑。

帮助我们改进文档

发现翻译问题或内容错误?请告诉我们。