理解浏览器渲染
解释浏览器渲染网页的过程,浏览器如何解析和应用样式,如何加载和执行脚本,渲染过程中各种资源的阻塞行为及其相应的事件。
DOM
JavaScript
异步
性能
重绘
浏览器渲染
由于现在广泛使用的屏幕都有固定的刷新率(比如最新的一般在 60Hz),
在两次硬件刷新之间浏览器进行两次重绘是没有意义的只会消耗性能。
浏览器会利用这个间隔 16ms(1000ms/60)适当地对绘制进行节流,
因此 16ms 就成为页面渲染优化的一个关键时间。
尤其在异步渲染中,要利用 流式渲染 就必须考虑到这个渲染帧间隔。
TL;DR
为方便查阅源码和相关资料,本文以 Chromium 的 Blink 引擎为例分析。如下是一些分析结论:
一个渲染帧内 commit 的多次 DOM 改动会被合并渲染;
耗时 JS 会造成丢帧;
渲染帧间隔为 16ms 左右;
避免耗时脚本、交错读写样式以保证流畅的渲染。
CSS
DOM
JavaScript
性能
浏览器渲染
页面资源的最佳世间是把页面样式写在 HTML 头部,页面脚本放在 HTML 尾部。这是因为脚本和样式会阻塞 DOM 渲染。
本文具体分析了包括脚本和样式在内的资源元素对 DOM 解析和页面渲染的影响,并给出具体的示例代码。
本文只讨论服务器端渲染的 DOM(以下称为同步渲染)资源载入时机。
关于在客户端 JavaScript 动态执行插入 HTML 标签(异步渲染)的阻塞情况请参考
异步渲染 DOM 元素的加载时机 一文。
TL; DR
CSS(外链或内联)会阻塞 整个 DOM 的渲染(Rendering),然而 DOM 解析(Parsing)会正常进行
很多浏览器中,CSS 会延迟脚本执行和 DOMContentLoaded 事件
JS(外链或内联)会阻塞 后续 DOM 的解析(Parsing),延迟 DOMContentLoaded,后续 DOM 的渲染(Rendering)也将被阻塞
JS 前的 DOM 可以正常解析(Parsing)和渲染(Rendering)
CSS
DOM
DOM解析
异步
浏览器渲染
在CSS/JS对DOM渲染的影响一文
探讨了静态页面中的JavaScript/CSS的载入和解析对DOM渲染的影响。
本文接着讨论异步渲染场景下JavaScript/CSS对DOM解析(Parsing)和渲染(Rendering)的影响。
TL;DR
动态插入的外部样式表或脚本不阻塞DOM解析或渲染。
动态插入的内联样式表或脚本会阻塞DOM解析和渲染。
未连接到DOM树的样式表或脚本(外部或内联)不会被下载、解析或执行。
可以通过onload和onerror监听HTML资源标签载入结果,兼容IE需要onreadystatechange。
async
defer
JavaScript
异步
性能
浏览器渲染
本文通过几个例子详述脚本对页面渲染的影响,以及浏览器正在加载提示
(标签页旋转按钮、页面停止渲染、光标停止响应)的行为。
介绍如何使用异步脚本载入策略提前 load 事件,提前结束浏览器的正在加载提示。TL;DR:
脚本会阻塞 DOM 渲染,因此可以把不必要首屏载入的脚本异步载入。
载入方式一:使用类似 requirejs 的方案,或在 load 事件后再插入外链脚本。
载入方式二:XHR 获取内容后 Eval(不安全,且跨域不可用)。
载入方式三:使用 <script> 的 async 和 defer 属性。
本文用来探讨 HTML 渲染机制中,如何不阻塞地加载脚本。对于生产环境,建议直接使用类似 AMD 这样的成熟方案。