证明浏览器遇到 <script> 块会阻塞渲染

115 阅读1分钟

前情提要

在昨日的周题会上,讲到了浏览器渲染问题。但是在证明 遇到 <script> 阻塞时,<script>块前面的元素在页面上是否已经显示 的问题上,大家存在疑惑,还一直证明不出来……

最后通过资料整理出以下知识点

浏览器渲染机制

  1. 解析 HTML,生成 DOM 树(DOM)
  2. 解析 CSS,生成 CSSOM 树(CSSOM)
  3. 将 DOM 和 CSSOM 合并,生成渲染树(Render-Tree)
  4. 计算渲染树的布局(Layout)
  5. 将布局渲染到屏幕上(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>

用谷歌浏览器打开,发现 北京 字段会先显示,然后隔一段时间后再显示 上海 ,证明结束