React 编译器可以逐步采用,允许你先在代码库的特定部分试用它。本指南将向你展示如何在现有项目中逐步推出编译器。

你将学习到

  • 为什么建议逐步采用
  • 使用 Babel 覆盖进行基于目录的采用
  • 使用“use memo”指令进行选择性编译
  • 使用“不要记忆”指令来排除组件
  • 带门控的运行时功能标志
  • 监控你的采用进度

为什么要逐步采用?

🌐 Why Incremental Adoption?

React 编译器旨在自动优化你的整个代码库,但你不必一次性全部采用它。渐进式采用让你可以控制推出过程,使你能够先在应用的小部分上测试编译器,然后再扩展到其他部分。

🌐 React Compiler is designed to optimize your entire codebase automatically, but you don’t have to adopt it all at once. Incremental adoption gives you control over the rollout process, letting you test the compiler on small parts of your app before expanding to the rest.

从小处开始有助于你建立对编译器优化的信心。你可以验证使用编译代码时应用的行为是否正确,测量性能提升,并识别特定于你的代码库的任何边缘情况。这种方法对需要稳定性的生产应用尤其有价值。

🌐 Starting small helps you build confidence in the compiler’s optimizations. You can verify that your app behaves correctly with compiled code, measure performance improvements, and identify any edge cases specific to your codebase. This approach is especially valuable for production applications where stability is critical.

增量采用还使得处理编译器可能发现的任何 React 规则违规变得更容易。你可以不必一次性修复整个代码库中的违规,而是可以在逐步扩大编译器覆盖范围的过程中系统地解决它们。这使迁移过程更可控,并降低引入错误的风险。

🌐 Incremental adoption also makes it easier to address any Rules of React violations the compiler might find. Instead of fixing violations across your entire codebase at once, you can tackle them systematically as you expand compiler coverage. This keeps the migration manageable and reduces the risk of introducing bugs.

通过控制代码中哪些部分被编译,你还可以运行 A/B 测试来衡量编译器优化在现实中的影响。这些数据可以帮助你对全面采用做出明智决策,并向你的团队展示其价值。

🌐 By controlling which parts of your code get compiled, you can also run A/B tests to measure the real-world impact of the compiler’s optimizations. This data helps you make informed decisions about full adoption and demonstrates the value to your team.

增量采用方法

🌐 Approaches to Incremental Adoption

逐步采用 React Compiler 的主要方法有三种:

🌐 There are three main approaches to adopt React Compiler incrementally:

  1. Babel 覆盖 - 将编译器应用于特定目录
  2. 使用“use memo”选择加入 - 仅编译明确选择加入的组件
  3. 运行时门控 - 使用功能标志控制编译

所有方法都允许你在全面推出之前在应用的特定部分测试编译器。

🌐 All approaches allow you to test the compiler on specific parts of your application before full rollout.

基于目录的 Babel 覆盖采用

🌐 Directory-Based Adoption with Babel Overrides

Babel 的 overrides 选项让你可以对代码库的不同部分应用不同的插件。这对于逐目录地采用 React 编译器非常理想。

🌐 Babel’s overrides option lets you apply different plugins to different parts of your codebase. This is ideal for gradually adopting React Compiler directory by directory.

基本配置

🌐 Basic Configuration

首先将编译器应用于特定目录:

🌐 Start by applying the compiler to a specific directory:

// babel.config.js
module.exports = {
plugins: [
// Global plugins that apply to all files
],
overrides: [
{
test: './src/modern/**/*.{js,jsx,ts,tsx}',
plugins: [
'babel-plugin-react-compiler'
]
}
]
};

扩展覆盖范围

🌐 Expanding Coverage

随着你逐渐熟悉,可以添加更多目录:

🌐 As you gain confidence, add more directories:

// babel.config.js
module.exports = {
plugins: [
// Global plugins
],
overrides: [
{
test: ['./src/modern/**/*.{js,jsx,ts,tsx}', './src/features/**/*.{js,jsx,ts,tsx}'],
plugins: [
'babel-plugin-react-compiler'
]
},
{
test: './src/legacy/**/*.{js,jsx,ts,tsx}',
plugins: [
// Different plugins for legacy code
]
}
]
};

使用编译器选项

🌐 With Compiler Options

你还可以为每个覆盖配置编译器选项:

🌐 You can also configure compiler options per override:

// babel.config.js
module.exports = {
plugins: [],
overrides: [
{
test: './src/experimental/**/*.{js,jsx,ts,tsx}',
plugins: [
['babel-plugin-react-compiler', {
// options ...
}]
]
},
{
test: './src/production/**/*.{js,jsx,ts,tsx}',
plugins: [
['babel-plugin-react-compiler', {
// options ...
}]
]
}
]
};

使用 “use memo” 选择加入模式

🌐 Opt-in Mode with “use memo”

为了获得最大的控制,你可以使用 compilationMode: 'annotation' 仅编译明确通过 "use memo" 指令选择加入的组件和钩子。

🌐 For maximum control, you can use compilationMode: 'annotation' to only compile components and hooks that explicitly opt in with the "use memo" directive.

注意

这种方法让你可以对各个组件和钩子进行精细控制。当你想在不影响整个目录的情况下测试特定组件的编译器时,这非常有用。

注解模式配置

🌐 Annotation Mode Configuration

// babel.config.js
module.exports = {
plugins: [
['babel-plugin-react-compiler', {
compilationMode: 'annotation',
}],
],
};

使用指令

🌐 Using the Directive

在你想要编译的函数开头添加 "use memo"

🌐 Add "use memo" at the beginning of functions you want to compile:

function TodoList({ todos }) {
"use memo"; // Opt this component into compilation

const sortedTodos = todos.slice().sort();

return (
<ul>
{sortedTodos.map(todo => (
<TodoItem key={todo.id} todo={todo} />
))}
</ul>
);
}

function useSortedData(data) {
"use memo"; // Opt this hook into compilation

return data.slice().sort();
}

使用 compilationMode: 'annotation' 时,你必须:

🌐 With compilationMode: 'annotation', you must:

  • "use memo" 添加到你想要优化的每个组件中
  • "use memo" 添加到每个自定义钩子
  • 请记住将其添加到新组件中

这可以让你在评估编译器的影响时精确控制要编译的组件。

🌐 This gives you precise control over which components are compiled while you evaluate the compiler’s impact.

运行时功能开关及门控

🌐 Runtime Feature Flags with Gating

gating 选项使你能够通过功能标志在运行时控制编译。这对于运行 A/B 测试或根据用户群体逐步推出编译器非常有用。

🌐 The gating option enables you to control compilation at runtime using feature flags. This is useful for running A/B tests or gradually rolling out the compiler based on user segments.

门控工作原理

🌐 How Gating Works

编译器将在运行时检查中封装优化后的代码。如果门返回 true,则运行优化版本。否则,运行原始代码。

🌐 The compiler wraps optimized code in a runtime check. If the gate returns true, the optimized version runs. Otherwise, the original code runs.

门控配置

🌐 Gating Configuration

// babel.config.js
module.exports = {
plugins: [
['babel-plugin-react-compiler', {
gating: {
source: 'ReactCompilerFeatureFlags',
importSpecifierName: 'isCompilerEnabled',
},
}],
],
};

实现功能标志

🌐 Implementing the Feature Flag

创建导出门控函数的模块:

🌐 Create a module that exports your gating function:

// ReactCompilerFeatureFlags.js
export function isCompilerEnabled() {
// Use your feature flag system
return getFeatureFlag('react-compiler-enabled');
}

采用故障排除

🌐 Troubleshooting Adoption

如果你在采用过程中遇到问题:

🌐 If you encounter issues during adoption:

  1. 使用 "use no memo" 临时排除有问题的组件
  2. 查看调试指南以了解常见问题
  3. 修复 ESLint 插件识别出的 React 规则违规
  4. 考虑使用 compilationMode: 'annotation' 来逐步采用

下一步

🌐 Next Steps