compilationMode

compilationMode 选项控制 React 编译器如何选择要编译的函数。

🌐 The compilationMode option controls how the React Compiler selects which functions to compile.

{
compilationMode: 'infer' // or 'annotation', 'syntax', 'all'
}

参考

🌐 Reference

compilationMode

控制 React 编译器优化哪些函数的策略。

🌐 Controls the strategy for determining which functions the React Compiler will optimize.

类型

🌐 Type

'infer' | 'syntax' | 'annotation' | 'all'

默认值

🌐 Default value

'infer'

选项

🌐 Options

  • 'infer'(默认):编译器使用智能启发式方法来识别 React 组件和 hooks:
    • 使用 "use memo" 指令明确注释的函数
    • 名称像组件(PascalCase)或钩子(use 前缀)的函数,并且创建 JSX 和/或调用其他钩子
  • 'annotation':仅编译明确标记了 "use memo" 指令的函数。非常适合渐进式采用。
  • 'syntax':仅编译使用 Flow 的 componenthook 语法的组件和钩子。
  • 'all':编译所有顶层函数。不推荐,因为可能会编译非React函数。

注意事项

🌐 Caveats

  • 'infer' 模式要求函数遵循 React 命名约定才能被检测到
  • 使用 'all' 模式可能会通过编译实用函数而对性能产生负面影响
  • 'syntax' 模式需要 Flow,无法与 TypeScript 一起使用
  • 无论模式如何,带有 "use no memo" 指令的函数总是被跳过

用法

🌐 Usage

默认推断模式

🌐 Default inference mode

默认的 'infer' 模式适用于大多数遵循 React 规范的代码库:

🌐 The default 'infer' mode works well for most codebases that follow React conventions:

{
compilationMode: 'infer'
}

在此模式下,以下函数将被编译:

🌐 With this mode, these functions will be compiled:

// ✅ Compiled: Named like a component + returns JSX
function Button(props) {
return <button>{props.label}</button>;
}

// ✅ Compiled: Named like a hook + calls hooks
function useCounter() {
const [count, setCount] = useState(0);
return [count, setCount];
}

// ✅ Compiled: Explicit directive
function expensiveCalculation(data) {
"use memo";
return data.reduce(/* ... */);
}

// ❌ Not compiled: Not a component/hook pattern
function calculateTotal(items) {
return items.reduce((a, b) => a + b, 0);
}

使用注释模式增量采用

🌐 Incremental adoption with annotation mode

对于逐步迁移,使用 'annotation' 模式只编译标记的函数:

🌐 For gradual migration, use 'annotation' mode to only compile marked functions:

{
compilationMode: 'annotation'
}

然后明确标记要编译的函数:

🌐 Then explicitly mark functions to compile:

// Only this function will be compiled
function ExpensiveList(props) {
"use memo";
return (
<ul>
{props.items.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
);
}

// This won't be compiled without the directive
function NormalComponent(props) {
return <div>{props.content}</div>;
}

使用 Flow 语法模式

🌐 Using Flow syntax mode

如果你的代码库使用 Flow 而不是 TypeScript:

🌐 If your codebase uses Flow instead of TypeScript:

{
compilationMode: 'syntax'
}

然后使用 Flow 的组件语法:

🌐 Then use Flow’s component syntax:

// Compiled: Flow component syntax
component Button(label: string) {
return <button>{label}</button>;
}

// Compiled: Flow hook syntax
hook useCounter(initial: number) {
const [count, setCount] = useState(initial);
return [count, setCount];
}

// Not compiled: Regular function syntax
function helper(data) {
return process(data);
}

禁用特定函数

🌐 Opting out specific functions

无论编译模式如何,都使用 "use no memo" 跳过编译:

🌐 Regardless of compilation mode, use "use no memo" to skip compilation:

function ComponentWithSideEffects() {
"use no memo"; // Prevent compilation

// This component has side effects that shouldn't be memoized
logToAnalytics('component_rendered');

return <div>Content</div>;
}

故障排除

🌐 Troubleshooting

组件未在推断模式下编译

🌐 Component not being compiled in infer mode

'infer' 模式下,确保你的组件遵循 React 约定:

🌐 In 'infer' mode, ensure your component follows React conventions:

// ❌ Won't be compiled: lowercase name
function button(props) {
return <button>{props.label}</button>;
}

// ✅ Will be compiled: PascalCase name
function Button(props) {
return <button>{props.label}</button>;
}

// ❌ Won't be compiled: doesn't create JSX or call hooks
function useData() {
return window.localStorage.getItem('data');
}

// ✅ Will be compiled: calls a hook
function useData() {
const [data] = useState(() => window.localStorage.getItem('data'));
return data;
}