完全搞懂 defer & async

完全搞懂 defer & async

DOMContentLoaded

image_1c443p1c3kkv6k414ri1l5k32m26.png-373.7kB

经过 chrome 浏览器的开发者工具能够直观的看到,图中蓝色的线和蓝色的字使用不一样的表现形式表示 DOMContentLoaded 这个事件触发的时间。chrome

咱们先来思考一个问题,如何衡量一个网页的加载速度?浏览器

在平常生活中,不少时候由于网络缘由咱们并不须要等待网页上的全部内容都加载完毕,而是只须要加载主要内容便可,好比你打开这篇博客时,可能并不须要等待全部图片都加载完成,而是看到博客的正文就能够正常阅读。也就是说,用户有时候只须要在空白的网页上看见内容就能够,而不须要等待全部内容都加载出来。服务器

那么如何衡量“计算这个网页从空白到出现内容所花费的时间”呢?HTML5 规范已经帮咱们完成相应的工做,即当一个 HTML 文档被加载和解析完成后,DOMContentLoaded 事件便会被触发。

浏览器向服务器请求到 HTML 文档后便开始解析(其产物是 DOM),到这里 HTML 文档就能够说是被加载和解析完成,同时若是有 CSS 文件则会根据 CSS 生成 CSSOM,而后再合并 DOM 和 CSSOM 生成渲染树,至此咱们已经知道全部节点的样式,下面便根据这些节点以及样式计算它们在浏览器中确切的大小和位置(即布局阶段),最后获得以上这些信息后,就能够把节点绘制到浏览器上。网络

image_1c4446ec51efa4guc0apa7gh72j.png-19.5kB

下面咱们要加入考虑 JavaScript:JavaScript 能够阻塞 DOM 的生成,也就是说当浏览器在解析 HTML 文档时,若是遇到(同步)脚本则中止解析,先去加载脚本并执行,执行结束后继续解析 HTML 文档。async

image_1c444h7sacvrctq91od5phrl30.png-1.2kB

defer

当 HTML 文档被解析时若是遇到 defer 脚本,则在后台加载脚本,文档解析过程不中断,等待文档解析结束以后,defer 脚本执行。工具

image_1c444j2o215um1poo1gl16kq12un3d.png-1.1kB

另外,defer 脚本的执行顺序与定义时的位置有关。布局

若是 script 标签中包含 defer,那么这一块脚本将不会影响 HTML 文档的解析,而是等到 HTML 解析完成后才会执行,而 DOMContentLoaded 只有在 defer 脚本执行结束后才会被触发。

HTML 文档解析不受影响,等 DOM 构建完成以后 defer 脚本执行,但脚本执行以前须要等待 CSSOM 构建完成,在 DOM & CSSOM 构建完毕,defer 脚本执行完成以后,DOMContentLoaded 事件触发。spa

async

当 HTML 文档被解析时若是遇到 async 脚本,则在后台加载脚本,文档解析过程不中断,脚本加载完成后,文档中止解析并执行脚本,执行结束后文档继续解析。3d

image_1c444knev1ch711jsa5pejt18an4q.png-1.2kB

当脚本下载完后当即执行,执行顺序不肯定。事件

若是 script 标签中包含 async,则 HTML 文档构建不受影响,解析完毕后 DOMContentLoaded 触发,而不须要等待 async 脚本执行、样式表加载等。

其余

  • 咱们在 jQuery 中常常使用的 $(document).ready(function() { // ...代码... }); 其实监听的就是 DOMContentLoaded 事件
  • 若是 script 无 src 属性,则 defer, async 会被忽略
  • 动态添加的 script 标签隐含 async 属性
相关文章
相关标签/搜索