关于javascript:Scripts-async-defer

一、背景

浏览器构建DOM树过程中遇到script标签就会暂定构建,并开始下载脚本,执行脚本,之后再持续构建DOM树。
并且绝对于文档,往往脚本文件体积大,并且网络下载的耗时比解析DOM树要大得多。

1.1 script标签的影响

阻塞浏览器构建DOM树(即便脚本并不会调用document.write),用户看到白屏(严格说是script标签前面的页面局部)工夫比拟长。

1.2 最佳实际

script标签放到body标签最初。

二、defer

通知浏览器能够异步下载内部脚本,不必期待下载执行,能够持续构建DOM树,等DOM树构建实现后才执行脚本。

下载:后盾并行下载(异步下载)
执行DOM构建后,但在DOMContentLoaded事件触发前
多个defer依照书写程序顺次串行形式执行。
defer不会阻塞DOM树构建,然而会阻塞DOMContentLoaded事件触发。

三、async

通知浏览器能够异步下载内部脚本,不必期待下载执行,能够持续构建DOM树,并且下载实现后就能够执行了。
针对齐全独立的脚本。不会依赖其余脚本,同时其余脚本也不能依赖 async脚本。

下载:后盾并行下载(异步下载)
执行:下载完就执行了。无需期待其余脚本,即先加载完的先执行。
async之间,以及和DOMContentLoaded事件处理函数执行程序是无序的。

留神:因为JS是单线程的如果在执行async脚本,此时其余工作就得暂定了,比方DOM树构建(不过这种状况很少见,除非JS脚本下载很快,并且DOM很大)

四、总结

下载程序 执行程序 DOMContentLoaded
async 异步并行下载,不阻塞DOM树构建 先加载完的先执行(Load-first Order) DOMContentLoaded无关,执行程序不定
defer async DOM构建后,依据文档程序顺次串行执行 DOM树构建后,但DOMContentLoaded事件触发前执行

相同点

  1. 都不会阻塞DOM树构建,都是异步下载,能够让用户先看到页面内容;
  2. 都不能够调用document.write,否则浏览器有个warning:

Failed to execute ‘write’ on ‘Document’: It isn’t possible to write into a document from an asynchronously-loaded external script unless it is explicitly opened.

差别点

  1. deferasync的惟一区别就是执行工夫点不同。

    • defer指推延执行(执行程序不变)
    • async指异步执行(执行程序不固定)

五、动静增加的脚本行为

5.1 通过document.createElement('script')形式增加脚本

通过document.createElement('script')形式创立的script对象,其async属性默认为true

let script = document.createElement('script');
console.log(script.async) // true
console.log(script.defer) // false

如果显示地设置script.async=false,则行为同defer,即便此时script.defer=false

5.2 通过document.write('<script src="xxxx"><\/script>')增加脚本

document.write自身的性能就是向文档流里插入内容,所以通过document.write('<script src="xxxx"><\/script>')增加脚本的成果同间接在文档里写script标签形式。

<script>
  document.write('<script defer src="./lib/normal.long.js"><\/script>')
</script>

<!-- 等价 -->
<script defer src="./lib/normal.long.js"><\/script>

六、Issues

6.1 同时增加async, defer的成果呢?

  1. 依照async成果执行;
  2. 因为async是HTML5才提出的,而defer是HTML4就有了,所以deferasync有更好的兼容性。同时增加async, defer的另一个成果是如果浏览器不反对async,则降级为defer
  3. 最佳实际就是把 script标签放到body标签最初,避免浏览器不反对async,也不反对defer

参考

整顿自GitHub笔记 Scripts: async, defer

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理