profiling
作为 React 为开发者提供的 “性能分析开关” ,通过独立的入口设计实现 分析能力与生产代码的物理隔离 , 体现 React 对性能调试体验的重视。
一、作用
profiling.js (该文件入口)是一个专用构建入口文件,核心作用是:启用与 React DevTools Profiler 深度集成的性能分析能力 , 同时保持与标准 react-dom 完全一致的 API。
1. 核心功能
- 增强渲染性能追踪 :
- 内部启用
enableProfilerTimer等标志,使 Fiber 架构在 commit 阶段自动记录组件渲染耗时、组件层级耗时等数据 - 这些数据通过 React DevTools 的 Profiler 面板 可视化展示(火焰图、 ranked chart 等),帮助定位性能瓶颈
- 内部启用
- 保留标准 API : 导出的
ReactDOM.render、createRoot等方法签名与标准入口完全相同,无需修改业务逻辑,仅需替换 import 路径 - (历史关联)与 Scheduler Tracing 集成 : 在 React 16 - 17 时期,需配合
scheduler/tracing的unstable_trace使用(标记异步操作范围)。⚠️ 注意: React 18+ 已移除scheduler/tracing,此用法已废弃,但profiling入口扔有效支持 DevTools Profiler
2. 使用方法
import ReactDOM from 'react-dom/profiling';
3. 关键注意事项
- 仅限开发/分析环境 : 因注入性能追踪逻辑,会带来显著运行时开销(约 10% - 30%), 严禁在生产环境使用。生产构建应使用标准
react-dom - 与
react/profiling区别 :react/profiling(React 核心包入口)提供<Profiler>组件等 APIreact-dom/profiling专注 DOM 渲染层的底层的计时能力,二者协同工作
- DevTools 依赖 : 数据通过安装 React DevTools 扩展才能可视化查看
- 版本演进 : React 18+ 扔保留入口已支持 Profiler 功能,但移除了对
scheduler/tracing的依赖,聚焦于 DevTools 集成
二、导出
if (process.env.NODE_ENV === 'production') {
// DCE check should happen before ReactDOM bundle executes so that
// DCE 检查应该在 ReactDOM 包执行之前进行,这样
// DevTools can report bad minification during injection.
// 开发工具可以在注入期间报告错误的压缩。
checkDCE();
module.exports = require('./cjs/react-dom-profiling.profiling.js');
} else {
module.exports = require('./cjs/react-dom-profiling.development.js');
}
三、工具
1. 检测开发环境
备注
为毛没有提取 checkDCE 到 "checkDCE.js" 文件,单纯的发牢骚
function checkDCE() {
/* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */
if (
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined' ||
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE !== 'function'
) {
return;
}
if (process.env.NODE_ENV !== 'production') {
// This branch is unreachable because this function is only called
// in production, but the condition is true only in development.
// Therefore if the branch is still here, dead code elimination wasn't
// properly applied.
// 这个分支是不可达的,因为这个函数只在生产环境中被调用,但是这个条件只在开发环境中为真。
// 因此如果这个分支仍然存在,说明死代码消除没有被正确应用。
// Don't change the message. React DevTools relies on it. Also make sure
// this message doesn't occur elsewhere in this function, or it will cause
// a false positive.
// 不要更改此消息。React DevTools 依赖它。同时确保这个消息,在该函数的其他地方不会出
// 现,否则会导致误报。
throw new Error('^_^');
}
try {
// Verify that the code above has been dead code eliminated (DCE'd).
// 验证上面的代码是否已被消除死代码 (DCE)。
__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(checkDCE);
} catch (err) {
// DevTools shouldn't crash React, no matter what.
// 不管怎样,开发者工具不应该让 React 崩溃。
// We should still report in case we break this code.
// 如果我们破坏了这段代码,仍然应该报告。
console.error(err);
}
}