React 组件性能分析工具——React Scan

为什么会产生React Scan这个分析工具?

我们知道,React 的性能优化有很多细节,以至于性能优化工作要做好会很琐碎且繁重。例如我们需要观测组件的封装力度、memo 的使用情况、hook/组件内的函数及数据定义、props 传参处理以及状态管理机制的设计等等等。
React Scan 团队将此关键原因归结于:The issue is that component props are compared by reference, not value. This is intentional – this way rendering can be cheap to run.,即“组件props是通过引用而不是值进行比较的”,React 的这个设计在带来了灵活性/实现简单的优势外,随之带来了容易导致不必要的渲染,使应用程序变慢,从而也使 React 性能问题分析具有较高的成本。

例如这个例子,onClick 函数和样式对象会在每次渲染时都要重新创建,这会导致组件拖慢应用的渲染速度:

1
<ExpensiveComponent onClick={() => alert('hi')} style={{ color: 'purple' }} />

React Scan 作为分析工具,目的就是降低 React 性能优化的分析成本。

介绍

React Scan 是一款开源的用于检测 React 应用渲染问题的工具,能自动检测和突出显示导致性能问题的渲染来帮助您识别这些问题,由 Aiden Bai 率先创建。它能够快速识别并报告潜在的性能瓶颈,帮助开发者优化应用性能。与传统的性能分析工具不同,React Scan 提供了一个简单的即插即用解决方案,可以通过脚本标签或 npm 包添加,以自动分析渲染性能,只需简单几步即可集成。

  • 自动渲染问题检测:React Scan 扫描您的 React 应用,查找可能导致性能问题的渲染问题。
  • 简单易用:它是一个轻量级的 JavaScript 库,您可以通过 script 标签或 npm 等方式轻松集成到您的项目中。
  • 快速集成:在任何其他脚本运行之前添加 React Scan 脚本,确保其能够准确地捕获渲染信息。

React Scan 通过其高效的渲染问题扫描功能,显著提升了 React 应用的性能和稳定性。它简化了开发流程,减少了调试时间,让开发者能够专注于核心业务逻辑。选择 React Scan,意味着您将获得一个更稳定、更高效的 React 应用,并显著提升开发效率。

使用

安装

npm 安装:

1
npm i react-scan -D

script 引入 js:

1
<script src="https://unpkg.com/react-scan/dist/auto.global.js"></script>

官方提供的地址有时候会不太稳定,建议单独保存部署一份

API

scan(options: Options)注册并启动分析工具

引入react之前进行注册,如

1
2
3
4
5
6
7
8
9
import { scan } from 'react-scan'; // import this BEFORE react
import React from 'react';

if (typeof window !== 'undefined') {
scan({
enabled: true,
log: true, // logs render info to console (default: false)
});
}
1
2
3
4
5
6
7
8
9
10
11
12
scan({
enabled: true, // 启用扫描
includeChildren: true, // 包含子组件
playSound: true, // 声音提示
log: false, // 控制台日志
showToolbar: true, // 显示工具栏
renderCountThreshold: 0,
report: false,
onCommitStart: () => {},
onRender: (fiber, render) => {},
onCommitFinish: () => {},
});
useScan(options: Options)hook 的方式进行注册并启动分析工具

参数同scan()

withScan(Component, options: Options)设定组件扫描

可将特定组件列入白名单,不扫描其他组件

1
2
3
4
5
withScan(Component, {
enabled: true,
log: true,
// ...其他配置项
});

getReport()获取性能报告

1
2
3
4
5
6
scan({ report: true });
const report = getReport();
for (const component in report) {
const { count, time } = report[component];
console.log(`${component}渲染${count}次,耗时${time}ms`);
}

setOptions(options: Options)/getOptions()设置/获取配置项

getRenderInfo(Component)获取指定组件渲染信息

使用效果

工具注册成功后,界面上会出现 React Scan 的工具栏,如:

p-use-01

工具栏默认会出现在界面右上角,我们也可以拖拽到界面其他地方

工具栏从左到右依次为:

  • 选择组件分析
    • 大概率与getRenderInfo()有关,后续有待分析源码
  • 开启/关闭实时分析
    • 大概率控制scan(),后续有待分析源码
  • 开启/关闭声音
    • 个人认为没啥用、提供情绪价值的功能
  • “react-scan”用来拖拽异动工具栏

p-use-02

工具使用也很简单,在实时分析打开的时候,我们操作界面就可以观察到各视图组件的渲染更新情况,以此来发现不必要的渲染动作。

p-use-03

如上图所示、不同层级之间的渲染更新通过颜色来区分。总体而言,个人感觉在中大型项目中还是很直观的。

*Monitoring监控能力

官方提供的 demo

https://dashboard.react-scan.com/project/demo

*对 React Native 的支持

从评论和官方处理来看,目前 RN 检测会有些问题,不过现阶段来看官网还是积极处理的、且目前反馈用例均已处理:

https://github.com/aidenybai/react-scan/pull/23

p-rn-01.png

原理

React Scan 工作原理主要是通过监控 React 的协调过程。该过程在更新时比较组件的前后快照。当状态或属性发生变化时,React 需要执行 ‘diffing’ 以确定需要重新渲染的内容。React Scan 自动检测这些渲染周期,并通过视觉提示突出显示导致性能问题的组件。它分析组件树,识别由不稳定的属性或低效的更新模式引起的不必要的重新渲染。

其相关代码实现待后续跟进分析。。。


相关链接