网页性能优化

简介

群星科技树是由 Django 驱动,将群星的科技树解析交给前端渲染的一个项目。由于科技树版本有限可以缓存,所以主要的性能瓶颈就在于前端的脚本执行速度和 DOM 渲染速度上。如果能解决这些问题就能在一定程度上缓解页面过于缓慢的问题。

经过初步分析,主要的页面卡顿的地方在于三点:页面加载、页面拖动和页面搜索(搜索是由前端实现的,由于涉及到定位科技等问题,不适合由后端处理)

分析和优化

减少重排

重排是在网络浏览器中执行的一个流程,用于重新计算文档中各元素的位置和几何形状,以便重新呈现该文档的部分内容或全部内容。很多操作都会导致浏览器重绘/重排整个页面,根据这个列表,甚至有列举出不会强制重排的操作会更少的错觉。由于重排会阻止用户在浏览器中执行操作,因此最大限度的减少浏览器重排是非常有必要的。

这个项目中所有因为重排而影响性能的内容主要如下: 1.页面加载用了Treant.js,因为要画出一个树型的图。这个库本身就有一些性能问题,如果要绘制的节点特别多,性能问题尤其严重。而很不幸这个项目的节点可以说没有上限,基本上也在400左右,最多可以有1000多个。因此加载速度会非常缓慢。这里的主要性能瓶颈在于这个库犯的一些我认为很低级的错误: 他对于每一个节点,都进行了四次读取绘制窗口(基本上就是屏幕大小)的clientWidthclientHeight和一次读取该节点的offsetWidthoffsetHeight的操作 在该库的运算过程中,需要遍历两次整个树,每次都要在对每个节点操作后进行重排,这个性能能好就怪了。那么既然定位到了就好改了,读取一次clientWidthclientHeight存储起来,offsetWidthoffsetHeight直接使用已知的值(因为长宽确定,如果不是伪节点,值都是一样的,是伪节点值就是0 0)。第二个地方的处理比较粗暴,但是第一个地方实在是不应该。当然第二个如此改过是只适合该项目的操作,没什么普遍性,但很有效。如此操作后加载时间缩短了75%~85%,这个其实应该早点解决不应该拖这么晚的。

2.搜索功能中,输入框绑定了change事件,所以每当输入一个字母时都会执行搜索,并且给出可能的候选结果。这里对 DOM 增删了节点,重排是不可避免的。但是由于每次点开搜索框后,不可能再在不中断操作的情况下移动位置,因此还是有优化的空间的。在每次激活搜索框后,使用cloneNode(true)存储当前状态。当然这样记录的节点是没有计算的样式的,所以还需要把 CSS 样式里需要用到的值拿出来放到attribute里面(有坑,IE里attribute不能用style这个名字)

3.element.style是布局类的样式,改变这个样式也会导致重排;而transform属于合成属性,并不会导致重排,对transform的操作,会在一个独立的渲染层(RenderLayer)上进行。这个层上的 2D、3D 和透明度变化都只需要在 GPU 上即可完成,不需要重绘更不用重排。

优化动画

在上文的第三点,其实就是优化了拖动过程中的计算,但是毕竟只是靠事件驱动,性能上还是有一些问题,根据 Chrome 的性能分析器,实际上鼠标移动时 fps 仅有5~15帧,键盘操作时也只有8~12帧,因此这里必须要进行一些改进。

改进的方法是通过requestAnimationFrame来更新动画。使用 JavaScript 渲染时用requestAnimationFrame可以把渲染的工作交给浏览器,保证渲染帧率比较高。如此做后,鼠标拖动的帧率稳定在24fps左右,键盘操作的帧率稳定在30fps左右。

其他未应用的优化

对于这个项目而言基本能用到的优化就是上述两点。因为主要的性能都用在了 DOM 操作上面。如果有一些高负荷的计算,可以使用 Web Workers 来进行,或者如果想要更高的计算速度使用 WebAssembly。这样不会影响主页面的流畅度,减少主线程的执行时间,避免渲染堵塞。当然这个项目没有高负荷的计算需求所以用不到。



blog comments powered by Disqus
本作品采用知识共享署名-相同方式共享 3.0 未本地化版本许可协议进行许可。
Theme by [Codepiano], First Modified Version by [pengx17], Latest Modified Version by [iHamsterball]