前情提要
在昨日的周题会上,讲到了浏览器渲染问题。但是在证明 遇到 <script>
阻塞时,<script>
块前面的元素在页面上是否已经显示 的问题上,大家存在疑惑,还一直证明不出来……
最后通过资料整理出以下知识点
浏览器渲染机制
- 解析 HTML,生成 DOM 树(DOM)
- 解析 CSS,生成 CSSOM 树(CSSOM)
- 将 DOM 和 CSSOM 合并,生成渲染树(Render-Tree)
- 计算渲染树的布局(Layout)
- 将布局渲染到屏幕上(Paint)
CSS
- CSS 放在 head 中会阻塞页面渲染(页面渲染会等到 CSS 加载完成)
- CSS 阻塞 JS 执行(因为 GUI 线程和 JS 线程互斥,因为 JS 有可能会操作 DOM)
- CSS 不阻塞外部脚本的加载(不阻塞 JS 的加载,但阻塞 JS 的执行,因为浏览器会有预先扫描器)
JS
- 直接引入 JS 会阻塞页面的渲染(JS 线程和 GUI 线程互斥)
- 异步加载的 JS(script 标签中添加 defer 属性)不阻塞页面的解析
- 异步加载的 JS(script 标签中添加 async 属性)下载过程不阻塞页面的解析,下载完成后立即执行,执行过程会阻塞页面的解析
- JS 不阻塞资源的加载
- JS 顺序执行,阻塞后续 JS 逻辑的执行
最终证明
浏览器解析起会假设 inline js 会改变页面结构,所以使用 inline js 开销比较大。不要使用
document.write()
这种输出内容的方法,使用现代 W3C DOM 方法来为现代浏览器处理页面内容
最后看到一条上面的知识点,通过这个 inline js
,我们可以测试是否前面的元素已经在浏览器页面中显示
<body>
<h1>北京</h1>
<script>
document.write('<script src="http://thirdparty.com/b.js"><\/script>');
</script>
<h2>上海</h2>
</body>
用谷歌浏览器打开,发现 北京
字段会先显示,然后隔一段时间后再显示 上海
,证明结束