当前位置: 首页 > 后端技术 > PHP

使用Performance分析优化页面当页面发生变化时,所有节点都会更新

时间:2023-03-29 15:06:42 PHP

本文将介绍实际使用Performance优化页面的过程。总的来说,chrome性能工具让我们更容易在代码运行过程中发现问题出在哪里,方便对一些可能没有注意到的问题进行定位、分析和优化。原文首发于我的个人博客。渲染优化首先,我们分析整个详情页。整个页面的结构大致如下,主要包括三个部分:基本信息、可视化和时间轴。时间轴里面是时间轴的详细信息,包括表格和几类可视化等等,里面比较重。如图:图片说明我们点击记录查看进入页面的性能图:优化点1可以看到,当前页面渲染耗时将近1.2s,让我们看看问题出在哪里。放大渲染部分,我们发现在渲染时间轴的过程中,大部分时间都花在了展示各个时间节点的细节上,但默认情况下,它们是隐藏的。换句话说,我们已经对N个节点进行了不必要的渲染,干掉它们就行了。图片说明查看代码,发现是以下位置导致的。我们封装了一个展开的盒子,类似这样:隐藏它,但React仍然会渲染和计算虚拟dom。这里我们对其进行改造,使其只在展开时才渲染,并尽量将渲染结果缓存起来。修改完成后,我们会发现Scripting从之前的880+ms变成了670ms,减少了200ms左右:图片描述优化点2我们继续看,会发现当页面是初始化后,详情部分会有很多耗时的EvaluateScript,主要是报警详情右侧的类别和每个类别下的可视图像和详情造成的。clipboard.png我们可能会想,初始化的时候没有渲染,为什么还要花很长时间计算呢?继续追查,发现原因在这里:clipboard.png在整个details组件中,我们引用了包括http、tcp等所有类型的组件,然后根据类型匹配组件。每个组件可能包含各种类型的定义、分类和计算等,不仅增加了加载时间,还延长了初始化时间。显然,我们这样做是错误的。这里,我们可以使用懒加载的方式对其进行优化,只显示其对应类型的图,避免不必要的资源和计算时间的浪费。修改clipboard.png后,我们再次进行性能测试,发现进入页面时,details组件耗时从260ms变为不到2ms:clipboard.png和Scripting从670+ms变为415ms,这是减少了约250ms:clipboard.png至此,进入页面的时间从开始的1.2s左右,变成现在的0.7s左右。更新优化我们在点击时间线查看详情的时候,会进行几个操作。关闭其他打开的详细内容,展开当前详细内容,根据当前类型显示相应类型的详细内容,如上。这个过程会涉及到React的更新操作,我们来优化一下这个过程。优化点1首先我们点击录制按钮,然后点击展开,进行录制。我们会发现如下结果:clipboard.png点击展开按钮,Timeline组件重复渲染,显然这是不应该的,让我们看看是什么原因造成的。我们看到在整个timeline组件中,有这么一段代码,使用connect连接timeline组件中timeline和alertList的两个数据,其中alertList数据就是details中对应的告警列表。两组数据对应的变化都会映射到组件的更新上,比如时间线的伸缩,以及alertList的请求,请求成功或者失败等。clipboard.png按理来说就是请求对应的toalertList只对应当前展开内容的更新。因此,我们对此有几个修改方案:在timeline组件中弃用alertList的引用,保证alertList不会参与到timeline组件的整体更新中。将时间轴的渲染与细节的渲染分离,并通过其对应的数据通过PureComponent进行控制和更新,并使用shouldComponentUpdate进行优化。这里我们使用第一种方式来避免alertList对整个组件的影响。我们会发现,点击详情后,整个timeLine只进行了一次较大的更新,而详情的更新只在展开的组件中进行。Clipboard.png优化点2我们会发现,当某个时间点展开时,整个list列表的节点都会更新,如下图所示。显然这样的性能代价是极大的,并不重要。如果列表中的内容很多,很可能大量更新会导致页面卡顿。clipboard.png因为其他列表节点引用了alertListprop,当它发生变化时,所有节点都会更新,所以我们需要使用shouldComponentUpdate手动优化它://当switch状态发生变化时,会更新render,否则不需要shouldComponentUpdate(nextProps,nextState){constopened=_.get(this.props,'open')constwillOpen=_.get(nextProps,'open')if(opened===willOpen&&!willOpen){returnfalse}else{//类似于pureComponent用于浅比较return!_.isEqual(this.props,nextProps)||!_.isEqual(this.state,nextState)}}再次记录,我们发现只要当前Item更新一次后,整个Timeline的更新时间就缩短到了40ms以内,大大提升了体验。clipboard.png的其他优化过程与上述类似,此处不再赘述。总结通过性能工具一步步的优化,整个页面的渲染和更新性能有了很大的提升,同时我们也知道了在写代码的过程中需要注意的问题。简单总结一下:避免非显示状态的不必要渲染。必要时,手动进行懒加载,避免大模块营销页面,避免加载不必要的模块,保证显示组件道具的纯度,避免其他道具变化导致组件更新。如果有必要,使用shouldComponent进行手动优化。通常,可以使用PureComponent来避免不必要的组件更新。