一图说尽script的async、defer、type=module

1,160 阅读2分钟

asyncdefer.svg

这张从whatwg拿过来的图片说尽了asyncdefertype=module下载和执行时机

以下的同步异步都是相对于文档解析来说的。

  • script

当解析遇到不带属性的script标签时,浏览器停止解析html,转而下载script资源,在资源下载完成之后执行js代码,执行完成之后才继续html解析。

  • script defer

defer属性会让浏览器异步加载js的资源,等到html解析完成,才去执行js代码。本来在html加载解析之后,会触发DOMContentLoad事件,但是defer会导致这个事件延后,即在执行完defer资源的代码之后才会触发DOMContentLoad事件。

  • script async

async也是让浏览器异步下载js资源,但是会在资源下载完之后立刻解析执行,执行过程会阻塞html的解析。

  • script type="module"

当以es6模块方式加载js资源时,浏览器也是异步加载,但是会在文档解析完成之后再去执行代码。

  • script type="module" async

与单独的async表现相同,异步加载资源,同步执行代码。


补充于 2024.4.21

今天看来,asyncdefer 的行为虽然对下载有影响(都是异步加载),但更重要的是执行时间,或者说是与文档解析之间的关系。为什么这么说呢?看下这两个单词在英文里的解释或许能帮助理解这种说法:

async: not happening at the same time 不同时发生

defer: to delay something until a later time 延后一段时间(再发生)

将文档解析过程作为参考对象,async 强调 不与文档解析同时发生,所以它的脚本在下载完后立即执行且暂停文档解析过程(不同时发生);而 defer脚本 则会 延后一段时间,等待文档解析过程结束再执行脚步。当然 DOMContentLoaded 事件表明的是所有 DOM 解析且加载执行完成,自然会受到async的影响。