这张从whatwg
拿过来的图片说尽了async
,defer
,type=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
今天看来,async
和 defer
的行为虽然对下载有影响(都是异步加载),但更重要的是执行时间,或者说是与文档解析之间的关系。为什么这么说呢?看下这两个单词在英文里的解释或许能帮助理解这种说法:
async: not happening at the same time 不同时发生
defer: to delay something until a later time 延后一段时间(再发生)
将文档解析过程作为参考对象,async
强调 不与文档解析同时发生,所以它的脚本在下载完后立即执行且暂停文档解析过程(不同时发生);而 defer
脚本 则会 延后一段时间,等待文档解析过程结束再执行脚步。当然 DOMContentLoaded
事件表明的是所有 DOM
解析且加载执行完成,自然会受到async
的影响。