通过chrome去了解html解析过程以及script标签defer、async区别

前言

之前看一篇介绍script标签中defer和async区别的文章。今天想利用chrome浏览器的Performance面板把知识再次巩固一下

先来一张经典图

  1. 无属性。当解析到当前位置时,会暂停html解析,去下载script资源,然后执行,执行完毕后继续html解析
  2. defer属性。一边下载script资源一边进行html解析,当资源下载完毕后会等待html解析完成后再执行,不会占用html解析时间
  3. async属性。一边下载script资源一边进行html解析,当资源下载完毕后会立即执行,执行期间html解析暂停,待执行完毕后继续html解析

主要区别:下载完成后是否立马执行,是否阻塞html解析

下面利用chrome浏览器的Performance面板来佐证上面的结论(下面分析均在无痕模式下进行,减少其他数据的干扰)

script依赖关系:bootstrap依赖jquery,backbone依赖underscore(backbone内部有些方法也依赖jquery,如果不调用就没事)

script标签无任何属性

xml 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Document</title>
    <link
      href="http://libs.baidu.com/bootstrap/3.0.3/css/bootstrap.css"
      rel="stylesheet"
    />
    <link
      href="https://cdn.staticfile.org/foundation/6.0.1/css/foundation.css"
      rel="stylesheet"
    />
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.5.17/vue.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/2.0.0/jquery.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/2.3.2/js/bootstrap.js"></script>
  </head>
  <body>
    <ul>
      <li>这是li标签</li>
    </ul>
  </body>
  <script src="https://cdn.bootcdn.net/ajax/libs/underscore.js/1.13.6/underscore-min.js"></script>
  <script src="https://cdn.bootcdn.net/ajax/libs/backbone.js/0.9.2/backbone-min.js"></script>
</html>

图1

从图中可以看出Parse HTML与资源下载是同时进行的,并不是说只有解析到相对应的外部资源才会去下载,这也是浏览器做的一个预解析器优化策略。

其中五个外部javascript资源,下载完成的顺序依次是backbone、bootstrap、underscore、jquery、vue

图2

图3 解析css资源

图4

当前html解析暂停,等待vue资源下载完成并执行后继续解析html(这里恰好是vue下载完后其余的js资源均下载完成了,所以只有一次html解析)

虽然别的资源早于vue下载完成,但是因为js资源是从上到下执行,所以必须要等到上一个资源执行完成之后才会继续执行下一个js

图5

这里是backbone下载较慢,所以执行完后面还要继续html解析

至此script标签无任何属性分析完毕

总结

  1. html解析和外部资源下载是同步进行的
  2. js资源下载完成后会执行,执行期间会暂停html解析,执行完之后继续html解析
  3. js资源是严格的按照从上到下的顺序执行,哪怕一些资源已经下载完毕,也要等上一个资源执行完之后才会执行

script标签:async

xml 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Document</title>
    <link
      href="http://libs.baidu.com/bootstrap/3.0.3/css/bootstrap.css"
      rel="stylesheet"
    />
    <link
      href="https://cdn.staticfile.org/foundation/6.0.1/css/foundation.css"
      rel="stylesheet"
    />
    <script
      async
      src="https://cdn.bootcdn.net/ajax/libs/vue/2.5.17/vue.js"
    ></script>
    <script
      async
      src="https://cdn.bootcdn.net/ajax/libs/jquery/2.0.0/jquery.js"
    ></script>
    <script
      async
      src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/2.3.2/js/bootstrap.js"
    ></script>
  </head>
  <body>
    <ul>
      <li>这是li标签</li>
    </ul>
  </body>
  <script
    async
    src="https://cdn.bootcdn.net/ajax/libs/underscore.js/1.13.6/underscore-min.js"
  ></script>
  <script async src="https://cdn.bootcdn.net/ajax/libs/backbone.js/0.9.2/backbone-min.js"
  ></script>
</html>

图1

其中五个外部javascript资源,下载完成的顺序依次是vue、jquery、bootstrap、backbone、underscore

从图1可以看出,script执行顺序不再是按照书写的顺序执行,而是谁先下载完成谁执行,这种机制会导致js之间的依赖关系错乱,可能会导致某些内部js报错

图2

因backbone.js比underscore.js先执行,所以backbone.js内部报错

图3

async属性会降低页面下载的优先级

总结

  1. 如果页面对于js资源有严格的执行顺序,最好不要使用async属性
  2. 资源下载完成后会立马执行,且会阻塞解析html(上图没有体现阻塞html,主要是因为资在第一个资源下载完成后html解析就已经完成了)
  3. async会影响当前资源下载的优先级

script标签:defer

xml 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Document</title>
    <link
      href="http://libs.baidu.com/bootstrap/3.0.3/css/bootstrap.css"
      rel="stylesheet"
    />
    <link
      href="https://cdn.staticfile.org/foundation/6.0.1/css/foundation.css"
      rel="stylesheet"
    />
    <script
      defer
      src="https://cdn.bootcdn.net/ajax/libs/vue/2.5.17/vue.js"
    ></script>
    <script
      defer
      src="https://cdn.bootcdn.net/ajax/libs/jquery/2.0.0/jquery.js"
    ></script>
    <script
      defer
      src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/2.3.2/js/bootstrap.js"
    ></script>
  </head>
  <body>
    <ul>
      <li>这是li标签</li>
    </ul>
  </body>
  <script
    defer
    src="https://cdn.bootcdn.net/ajax/libs/underscore.js/1.13.6/underscore-min.js"
  ></script>
  <script
    defer
    src="https://cdn.bootcdn.net/ajax/libs/backbone.js/0.9.2/backbone-min.js"
  ></script>
</html>

图1

图2

defer属性会使js资源在html解析完成后按照顺序执行,会降低下载资源的优先级

总结

  1. defer不阻塞html解析进度,资源全部下载完成后会按照顺序执行
  2. defer会影响资源下载的优先级

结语

  1. html解析和资源下载是同步进行的,并不是解析到当前位置才会触发下载
  2. script标签会阻塞当前html解析,当资源下载和执行完毕后继续html解析
  3. async和defer不阻塞html解析,区别是async属性在下载完成后会立即执行,执行顺序不能保证,执行时会阻塞html解析,defer则会在html解析完成后执行,会按照顺序执行
  4. js如果有严格的依赖关系则不能使用async
  5. 建议使用defer属性,既能保证执行顺序,也不阻塞html解析
相关推荐
码界领航12 分钟前
【2025最新版】Chrome谷歌浏览器如何能恢复到之前的旧版本
前端·chrome
乐多_L1 小时前
使用vue3框架vue-next-admin导出表格excel(带图片)
前端·javascript·vue.js
南望无一1 小时前
React Native 0.70.x如何从本地安卓源码(ReactAndroid)构建
前端·react native
Mike_188702783511 小时前
1688代采下单API接口使用指南:实现商品采集与自动化下单
前端·python·自动化
鲨鱼辣椒️面1 小时前
HTML视口动画
前端·html
一小路一1 小时前
Go Web 开发基础:从入门到实战
服务器·前端·后端·面试·golang
堇舟1 小时前
HTML第一节
前端·html
纯粹要努力2 小时前
前端跨域问题及解决方案
前端·javascript·面试
小刘不知道叫啥2 小时前
React源码揭秘 | 启动入口
前端·react.js·前端框架
kidding7232 小时前
uniapp引入uview组件库(可以引用多个组件)
前端·前端框架·uni-app·uview