文章内容大多来自学习摘记、实践思考。
浏览器加载过程
浏览器从服务器接收 HTML,把 HTML 在内存中转换成 DOM 树,在转换的过程中遇到:
- CSS 或 image 请求,不会阻塞 HTML 的解析、不需要等请求的返回,当返回后,只需要把返回的内容放入到 DOM 树中对应的位置。
- JS 请求。因为 JS 有可能直接改变 DOM 树结构,为了不重新构建 DOM 树,会阻塞其他的下载和浏览器渲染。
参考:网页渲染过程、JavaScript Loading Priorities in Chrome、让我们再聊聊浏览器资源加载优化
性能优化
html 优化:
- 根据关键渲染路径、首先加载最小可用的 css js 资源,script 标签可以用 async 标记 (分析关键渲染路径)。
- 在 head 里面尽量不引入 js, CSS 下面不能有任何的 JS 标签(包括内联JS),否则会阻塞 HTML 的解析。如果必须要在头部增加内联脚本,一定要放在 CSS 标签之前 (WebView性能、体验分析与优化)。
- repaint:当某元素在不改变布局、发生显示/隐藏的变化时,就会发生 repaint。
- reflow:当 DOM 以一种影响到布局的方式进行操作时,会触发 reflow。
- 例如,样式改变影响了布局、className 改变、浏览器窗口大小改变、插入一个新元素、改变文本、新增一个元素属性。当元素 reflow 时,他的子节点和其后的任何元素也会 reflow,最后所有元素进行 repaint。
- 通过 getComputedStyle、offsetWidth、scrollWidth、clientWidth 等属性获取元素的尺寸或位置,会强行触发 reflow。
- 减少 reflow 的方法:
- 多 style 变化可通过设置一次 className 完成。
- 将多个元素改变都在 DOMDocumentFragment 中进行,然后用一次操作将元素片段放到 DOM 中,这样只触发一次 reflow。
- 要在元素上做动画应该设置
position: absolute | fixed
, 他们只会引发一个 repaint 而不是全部 reflow。 - 通过
scrollTo()
进行原生滚动,性能显著,因为没有触发 reflow。
参考:Minimizing browser reflow、js-repaint-perfs、js-repaint-perfs
dom 优化:
- 删除 dom 对象时,及时删除事件监听。
- js 对象引用操作 dom 对象后,需要设置为 null 或 delete 掉。
- 尽量少访问 dom。
- be aware that although JavaScript engines continue to get faster, the next real bottleneck is the DOM.
- Don’t load from uninitialized or deleted elements.
- 使用 innerHTML 把一大块元素替换掉,因为销毁的元素比较多、绑定着事件,会导致 GC 压力大。再插入新元素,再重新绑定事件。整体性能耗费比较大。
js 优化:
Garbage collection 是内存管理机制,在 runtime 时自动运行、不受 js 控制。如果某个变量引用是对对象的最后一个引用,那么垃圾回收会自动执行。 全局变量不会被垃圾回收,除非页面刷新、跳转或关闭。
函数作用域里的变量,在函数执行完毕、函数退出、没有引用时会被清理掉。 本来 Javascript 引擎能检测正在执行中的 “热” 对象并优化它、让它执行更快速;但 delete 操作会「严重改变」对象结构,导致引擎不能优化该对象。
将不需要的对象属性设置为 null 也比 delete 操作好,但这也是不必要的。
一些 tips:
- Don’t write enormous functions, as they are more difficult to optimize.
- 避免在一个数组里存在不同数据类型 (e.g. numbers, strings, undefined or true/false)
- call 比 apply 性能好!参考(angular1.0.6:2848行;backbone1.0.0:200行)
eval()
、window.eval
、new Function
第一个不会被 GC 回收,后两个可以被 GC 回收。每次使用他们时都会调用脚本引擎将源代码转换成可执行代码;因此尽量避免使用。
参考:writing-fast-memory-efficient-javascript、JavaScript 启动性能瓶颈分析与解决方案、Memory Analysis 101