提升页面性能

问题的起因于在实现一个移动端滑动功能时的,性能有些差,尤其在便宜的安卓机上表现尤为如此,故展开了优化的探索…

浏览器如何工作

  1. 首先理解下webkit的渲染过程
  2. 再来理解下reflow-repaint-restyle-relayout渲染术语
  3. 浏览器是如何工作的
  4. reflow/layout:回流/布局。 比如改变node尺寸之类的需要重新计算布局的操作,会引发reflow,页面初始化时会第一次reflow。
  5. repaint:重绘。将重新计算完的结果更新在渲染树上叫repaint。

总之这些渲染过程都是耗时的,我们要做的就是从各个方面尽可能减少这些耗时的过程减少重绘区域的大小合理利用硬件资源,最终提升性能和优化体验。这三个方面以下都会提到具体的措施。

硬件加速

使用一些相关的css属性可以调起终端设备的GPU对页面进行渲染而非普通的浏览器渲染,并适当减少重绘,可以提升渲染的速度,这便是以上提到的合理利用硬件资源

使用一些对样式没有影响的CSS3D属性可以唤起硬件加速获得较好的渲染效果。过多的使用ccs3D等变换会提高内存占用,反而影响性能,总之一句话,合理利用硬件资源以获得最佳的展现效果(废话)。

css属性触发

籽料奉上,该API提供了css属性分别引起浏览器怎样的重绘或者重排。
该文章 中提到一个非常有用的概念,position:fixed对重绘区域的影响。每当scrolling时fixed定位的元素都会引起重绘,如果多个这种元素在页面上组成一个较大的重绘区域时会相当严重影响性能。例如这篇文章中提到的demo页相对窗口width:100%的fixed顶部导航栏和相对窗口height:100%的fixed右侧菜单栏组成一块全屏大小的绘制区域,scroll时明显的影响到了FPS(FPS面板中可以看到)。所以我们在使用fixed元素时,尽量避免他们在一个层中或者避免组成较大的绘制区域,即上面提到的减少重绘区域的大小

will chage

css提供了为元素添加will-change属性用来给浏览器一个提示,表明该元素即将在哪一个属性上发生变化,浏览器将提前准备而且将优化措施置于内存中。使得相应更快,更迅速。当然也是以消耗内存为前提的,所以最好精确化,最小化使用该属性而不是给无用的元素添加该属性。兼容性不是那么好,但总比没有强…

js优化

js对dom操作时引发的重绘与重排(有的叫回流)对于性能(尤其是重排)的影响很大。WEB前端开发这篇博客有较为翔细的解释(应该是翻译妈蛋),我找到了原文,优化目的只有一个,尽可能少的引起浏览器的重排/绘…以下算是重点:

  1. 尽量一次性执行style的操作,如放入cssText中,分步执行js操作会导致多次重绘重排。
  2. 缓存那些导致强制触发flush队列的js操作,比如操作offsetTop, offsetLeft等样式信息,具体可以触发的dom操作可以参考这位大哥整理的
  3. 对一个element进行频繁操作时, display:none,执行你的复杂的dom操作,然后恢复display原状态,这期间dom操作便不会引起重绘/排(真TM机智啊)…
  4. 对需要更新的node进行拷贝,然后一次性替换原node,说白了目的也是避免对dom直接的分步操作导致过多的重排重绘
  5. 使用DocumentFragments进行node集合的插入,John Resig的博客有提起,但是没有明显的指出与浏览器的重排重绘联系起来。

总之即减少耗时的渲染过程

requestAnimationFrame

大多数设备的屏幕刷新频率为60次/秒,即我们所说的FPS为60时,视觉体验较好。动画的执行建议用requestAnimationFrame而非setTimeout/setInterval,前者由浏览器厂商做了针对性的优化,针对不同刷新频率的设备能调整fps,能保证执行每一帧前回调函数都会执行(setInterval在执行队列中有实例存在时就会跳过本次实例的放入,导致丢失帧),反正就raf好~~至于具体为啥用requeAnimationFrame,请参考google前端大神html5rock中的具体阐述。

devtools

原谅我。。。我用的不熟,请自行Googleing chrome开发工具查找项目运行中性能的瓶颈。。。

从一开始编码时意识里就存在这些优化的套路,最后的效果绝逼是不一样的…