3.5 向 60 fps 进发(一):JavaScript 优化、Styles 优化 及 Layout 优化
不管 JS 还是 CSS 的部分,决定优化措施之前,先 profile 代码性能,找出瓶颈。这些东西是变化的,以实际性能分析数据说话。要养成「优化前先 profile」的意识。
It’s important to use “tools not rules!” because architectures change and bugs get fixed. Memorizing rules isn’t going to cut it when that happens. - Paul Lewis
JavaScript
因为有 JIT 的存在,你写的代码并不一定就是执行的代码。你是猜不到的,所以尽量不要做 micro-optimizations,效率很低
尽快运行 JS。它可能会导致整个渲染流程重新开始,必须在最开始尽早跑完。animation 阶段只有16ms,除去浏览器的调度开支,你所能用的只有10ms,留给 JS 的只有3-4ms 左右
使用 WebWorker 多线程进行无论如何需要很长耗时的工作。它与主渲染线程不会互相影响,仅通过消息来通信,类似于订阅者模式
- The basis of WebWorkers: https://www.html5rocks.com/en/tutorials/workers/basics/
- Mozilla WebWorker Documentation: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers
- 垃圾回收(GC)的东西。没讲太深,听不太懂,忽略不计
requestAnimationFrame()
。这个东西具体是个什么不太清楚,但大概是讲,每帧时间是16ms,但如果你的 JS 在帧中间再开始,可能整个渲染流程还没结束这帧就跑完了。这个函数就是确保浏览器调度的时候,能在帧的最开始运行 JS。但我还是不懂
Styles 优化
下面的原则,涉及大量元素的改动、选择时才尤为明显。数据量小的应用随便玩都不会遇到性能瓶颈的,就可以随意点
- 元素样式的改变,对性能的影响基本来说是线性的。也就是说,减少改动的元素,对性能有线性的改善作用
- 有的「样式改变」对性能影响较大,有些较小,这是可以理解的,有轻重
- 选择同一个元素,不同选择器性能也不同,越简单越直接性能越好。一般来说,绝对定位(id/class)> 相对定位(
nth:child
) & 逻辑关系定位(not:empty
)- BEM 方案 https://en.bem.info/methodology/key-concepts/
- 其他方案,记录尤雨溪有个 Live 有提到。可试分析对比 其会对性能造成的影响
最佳实践
总结起来就两点:
- 减少改动的元素
- 降低选择器的复杂度
Layout 优化
本来自然顺序就是先 JS 再 styles 再 layout。如果你在 JS 中执行一些触发 layout 的动作然后又执行了一些触发 styles 的动作,会导致什么呢?这次 layout 被无效化了。一两次可能无所谓,不过如果你是在循环中做这个事情,那就是不好的实践了。
- 每一个 CSS 样式变化会触发哪些阶段:https://csstriggers.com/
- Paul Irish: What forces a layout / reflow: https://gist.github.com/paulirish/5d52fb081b3570c81e3a
- 如何避免 layout 阶段的无效触发:http://gent.ilcore.com/2011/03/how-not-to-trigger-layout-in-webkit.html
- http://www.phpied.com/rendering-repaint-reflowrelayout-restyle/
最佳实践
- 不要在循环中 同时 触发 Styles 和 Layout 流程
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: 4.1 Ajax & APIs
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论