通过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解析
相关推荐
也无晴也无风雨1 小时前
深入剖析输入URL按下回车,浏览器做了什么
前端·后端·计算机网络
Martin -Tang2 小时前
Vue 3 中,ref 和 reactive的区别
前端·javascript·vue.js
FakeOccupational3 小时前
nodejs 020: React语法规则 props和state
前端·javascript·react.js
放逐者-保持本心,方可放逐4 小时前
react 组件应用
开发语言·前端·javascript·react.js·前端框架
曹天骄5 小时前
next中服务端组件共享接口数据
前端·javascript·react.js
阮少年、5 小时前
java后台生成模拟聊天截图并返回给前端
java·开发语言·前端
郝晨妤6 小时前
鸿蒙ArkTS和TS有什么区别?
前端·javascript·typescript·鸿蒙
AvatarGiser7 小时前
《ElementPlus 与 ElementUI 差异集合》Icon 图标 More 差异说明
前端·vue.js·elementui
喝旺仔la7 小时前
vue的样式知识点
前端·javascript·vue.js
别忘了微笑_cuicui7 小时前
elementUI中2个日期组件实现开始时间、结束时间(禁用日期面板、控制开始时间不能超过结束时间的时分秒)实现方案
前端·javascript·elementui