2025 年 10 月,React 官方正式发布了 React Compiler 1.0 稳定版。如果你两三年没碰 React 生态,可能觉得:”哦,又一个新工具。”但这次不一样——这东西大概率会改变你接下来几年的写代码方式。

这东西到底是什么?
简单说,React Compiler 是一个编译时优化工具。你跑构建的时候它跑一遍你的代码,自动分析哪些计算可以缓存、哪些函数该记下来、哪些组件不用重新渲染——然后帮你把优化逻辑塞进去。你什么都不用写,它自己干。
这个项目内部代号叫 React Forget,意思就是”忘掉手动优化这回事吧”。React 团队从 2022 年就开始搞,花了三年多才推到稳定版。
核心变化一句话:之前你手动写的 `useMemo`、`useCallback`、`React.memo`,大部分都不需要了。
手动优化的日子,真的受够了
写过两年以上 React 的话,下面这些场景你肯定不陌生。
项目刚开的时候,代码清清爽爽:
“`jsx
function ProductList({ products, filter }) {
const filtered = products.filter(p => p.category === filter);
const sorted = filtered.sort((a, b) => a.price - b.price);
const total = sorted.reduce((sum, p) => sum + p.price, 0);
return (
<div>
<p>总计: {total}</p>
<p>{sorted.map(p => <productcard key="{p.id}" product="{p}"></productcard>)}</p>
</div>
)
}
“`
跑着跑着发现性能不对,开始一个个往上堆 memo:
“`jsx
function ProductList({ products, filter }) {
const filtered = useMemo(
() => products.filter(p => p.category === filter),
[products, filter]
);
const sorted = useMemo(
() => [...filtered].sort((a, b) => a.price - b.price),
[filtered]
);
const total = useMemo(
() => sorted.reduce((sum, p) => sum + p.price, 0),
[sorted]
);
return (
<div>
<p>总计: {total}</p>
<p>{sorted.map(p => <productcard key="{p.id}" product="{p}"></productcard>)}
</p></div>
)
}
“`
看着就烦对吧?更烦的是依赖数组写错了查半天,还有那种祖传代码里到处是 useContextSelector 和几十个 memo 的,改起来跟拆地雷一样,炸了都不知道该怪谁。
React 团队自己也明白这个。Lauren Tan(React Compiler 负责人)发布时说了一段挺坦诚的话:”我们花了好多年教开发者怎么用 useMemo,现在又要告诉你们不用写了——确实有点讽刺。但我们觉得这才是正确的方向。”
它是怎么工作的?
React Compiler 不在运行时干活,而是在编译阶段对你的代码做静态分析。它用了不少编译器领域的成熟技术——控制流分析、数据流分析,还有自定义的 SSA(Static Single Assignment)IR 表示。
你写:
“`jsx
function UserProfile({ user }) {
const displayName = `${user.firstName} ${user.lastName}`.toUpperCase();
return <h1 class="wp-block-heading">{displayName}</h1>;
}
“`
编译器跑一遍能发现 `displayName` 只有 `user` 变了才需要重新算,于是自动帮你加了缓存。你完全看不到这些,源码还是干干净净。
React Compiler 遵循一套叫 “Rules of React” 的约束系统。只要你的代码符合规则——比如不直接改 state、不改变 hooks 调用顺序——编译器就能安全地帮你优化。eslint-plugin-react-hooks 的规则集已经跟编译器打通了,跑一遍 ESLint 就能提前知道哪些代码编译器处理不了。
如果你确实需要手动控制,可以在文件顶部加一行 `”use no memo”;`,编译器就会跳过这个文件。这是逃生阀,但绝大多数情况用不上。

各框架的集成情况
发布之后的生态跟进速度比我预想的快。
Next.js 从 15.3.1 开始稳定支持。Next.js 16 更是默认开箱即用——新建项目直接启用,零配置。
Expo SDK 54 及以上版本默认开启,新的 RN 项目一开就能用。这对 React Native 开发者来说是个好消息——移动端性能优化一直是老大难,大多数 RN 项目的 memo 覆盖率低得可怜。
Vite 这边有个坑。`@vitejs/plugin-react` v6 配合 Vite 8 把内置的 Babel 换成了 oxc,所以老的 `react({ babel: { plugins: […] } })` 写法跑不通了。正确做法是用 `@vitejs/plugin-react` 导出的 `reactCompilerPreset()` 方法。
还有个正在做的 swc 插件,目标是进一步提升构建性能。如果你特别在意构建速度,可以留意一下。
好消息和一些坑
好消息
– 新项目零配置享受自动优化
– ESLint 提前帮你排查编译器可能搞不定的代码
– Next.js、Expo、Vite 都第一时间跟进了
– 小项目编译后二进制体积基本没变化
需要注意的
– 老项目别急着删 useState 和 useCallback。直接删了可能跑出无限循环——编译器的逻辑可能跟你之前的手动缓存策略打架。安全做法是先启用编译器验证它能正常处理,运行稳定了再慢慢清理。
– effect 依赖还是要自己管。编译器不会帮你管 `useEffect` 的依赖,因为 effect 触发时机的精确控制和渲染优化是两码事。
– 代码必须符合 Rules of React。不遵守的话——比如直接改 props、hooks 不按顺序——编译器就安静地跳过,不会报错。所以建议先让 eslint-plugin-react-hooks 跑到零告警再开。
所以
React Compiler 1.0 不是实验品了,是可以上生产的东西。一句话概括:从”按约定优化”变成了”按编译优化”。
下一个你新建的 React 项目,大概率已经自带这能力了。你只管写干净的代码,编译器把脏活干了。至于老项目里的 useMemo 和 useCallback——先留着,别急着动。等编译器跑稳了再慢慢清也不迟。
毕竟好代码的标准从来不是”看起来优化了”,而是”真的不卡 + 你能看懂”。
📖 推荐阅读
这些也是跟前端工程师有关的文章,你可能会感兴趣: