原文来自:https://reactjs.org/blog/2018/09/10/introducing-the-react-profiler.html
关于性能分析的还有一篇文章:Airbnb 爱彼迎房源详情页中的 React 性能优化,可以一块结合看看~
React16.5开始,React DevTools开始支持新的一个插件。这个插件基于React实验型API,采集每个被渲染组件的时间信息。这样我们就可以明确了解我们React应用的瓶颈在哪里。这个插件同样兼容未来React即将推出的时间分片和挂起的特征。
如何找到收集数据
在React DevTools面板上能看到Profiler这个tab。
注意:
只有React16.5+的开发模式才支持Profiler。生产环境的profiling包也可以用来分析。
Profiler面板刚开始时空的,你需要点击录制按钮开始收集数据。
一旦你点击了录制按钮,DevTools就会在你每次render组件的时候自动收集信息。然后你就按照平时的方式正常操作。当你想要结束采集的时候,在点击下『Stop』按钮就可以了。
假设你的应用在你收集数据的时候至少render了一次,DevTools会通过几种不同的维度来展示React收集到的信息。
性能数据
浏览commits
理论上,React将工作分成了两个阶段:
- render阶段:确定哪些变化会作用到DOM上。在这个过程中,React会调用render,然后将render得出来的结果和之前render出来的结果对比。
- commit阶段:将变化应用到DOM上。(浏览器端,就是React插入,更新,删除DOM的过程)。这个阶段,React会调用componentDidMount和componentDidUpdate这两个生命周期。
React会根据commit将采集到的性能数据分组。显示如下:
图中每个bar表示一个commit。选中的bar显示为黑色。你可以点击选择任意一个bar。
每个bar的颜色和高度表示这个commit阶段的时间。高度黄色的bar要比矮的蓝色bar更加耗时。
过滤commits
采集的时间越长,应用render的次数就会越多。有时候,你可能会面临太多的commit,以至于很难处理。Profiler提供了一个过滤掉机制。我们可以定义一个阈值,Profiler就会隐藏掉那些快于阈值的commits。
火焰图
火焰图表示某个commit的状态。火焰图中的每个bar都表示一个Component(比如:App, Nav)。bar的大小和颜色表示渲染组件和他的子节点需要多长时间。bar的宽度表示组件上次渲染时花费的时间,颜色表示当前提交的时间花费了多少时间。
注意:
bar的宽度表示在上次渲染时渲染组件(及其子组件)所需的时间。如果组件在这次commit的时候,没有渲染,这个时间表示的就是之前的时间。bar越宽,需要渲染的时间就越长。
bar的颜色表示组件(及其子组件)在所选commit中render的时间。黄色组件表示消耗较长时间,蓝色消耗较少时间,灰色表示没有消耗时间。
比如说,上图表示,选中的commit渲染消耗了18.4ms。Router组件是最消费时间的(18.4ms)。这个时间主要分布在他的两个子组件上:Nav(8.4ms)和Route(7.9ms)。剩下的时间用来渲染组件自身和组件剩下的子组件。
你可以在火焰图上点击组件来放大缩小火焰图。
点击火焰图上的组件同时也表示你选中了它。这时,右侧会显示这个组件在这次commit中的信息,包括它的props和state。通过这些,你可以深入了解到本次commit中,组件到底render了什么:
在某些情况下,选定一个组件,在不同commits中切换,会了解这个组件是因为什么原因render。
上图显示,切换到这两个commit之间,只有state.scrollOffset
变化了,这很有可能就是List组件重新render的原因。
排名图
排名图表示的是一次commit。图中每个bar代表一个组件(比如说:App,Nav)。图中按序排列,所以一眼就能看出那个组件最消耗时间。
注意:
组件的render时间也包括了孩子的render时间,这个组件往往会在排名图上的前几个。
和火焰图一样,你也可以通过点击组件来放大,缩小图。
组件图
有时候,了解在采集期间,某个组件渲染了多少次对于我们开发非常有用。组件图通过一个bar图展示了这些信息。每个bar表示组件一次render消耗的时间。每个bar的颜色表示其相对于其它组件render消耗时间的晨读。
上图表示,List组件在采集的过程中,渲染了11次。从黄色可以看出,每一次渲染,List都最消耗时间。
如何得到组件图呢?在组件上双击,或者如下图一样操作就可以了。
如果选中的组件在采集的过程中没有render,就会如下图显示:
交互
React也增加了另外一个实验型API,用来追踪更新原因——“交互”。如下所示:
上图所示,我们在一个采集期,最终到了4个交互。图中的每一行都代表着一个被追踪到的交互。带有颜色的点表示这个追踪中,commit的时间。
你同样也可以从火焰图和排名图中看到某次commit与哪个交互有关:
你可以通过点击交互和commit来回切换:
目前这个API还是非常新,我们会在以后blog说详细说明。
常见问题答疑
No profiling data has been recorded for the selected root
如果你的应用存在多个根DOM,你在收集之后可能会看到下面这幅图:这个表示在你选中的根元素上,没有收集到数据。这种情况下,尝试切换别的跟元素:
No timing data to display for the selected commit
有时候,某个commit很快就结束了,以至于调用的performance.now()
没办法给DevTools有效信息。这种情况下就会出现这个现象: