async/defer

当浏览器加载 HTML 并遇到<script>...</script>标签时,它无法继续构建 DOM。它必须立即执行脚本。外部脚本<script src="..."></script>也是如此:浏览器必须等待脚本下载,执行下载的脚本,然后才能处理页面的其余部分。

这导致一个重要问题:

  • 如果页面顶部有一个庞大的脚本,它会“阻塞页面”。在下载并运行之前,用户无法看到页面内容

对于异步加载脚本,有defer和async两种方法:

defer

  • defer属性告诉浏览器不要等待脚本,浏览器会继续处理 HTML,构建 DOM。该脚本“在后台”加载,然后在 DOM 完全构建完成后再运行。

  • defer可用于对脚本执行顺序有严格要求的情况,defer脚本保持相对顺序来执行,即使后面的脚本先于前面的脚本加载完成,在执行时也会按照顺序来执行。就像常规脚本一样

  • defer脚本总是在 DOM 准备好时执行(但在DOMContentLoaded事件之前)。当纯 HTML 被完全加载以及解析时,DOMContentLoaded 事件会被触发,而不必等待样式表,图片或者子框架完成加载。

  • defer脚本可以看作是在DOM结构解析完毕后、DOMContentLoaded事件触发之前执行的HTML文档的一部分。DOMContentLoaded是一个在HTML文档被完全加载和解析后触发的事件,但在此事件触发时,不包括样式表、图片和子框架的加载完成。这个事件的触发标志着所有的HTML已被完全加载和解析,DOM树已经构建完毕,因此可以开始执行依赖于DOM的JavaScript代码。

  • defer脚本的执行是在HTML文档的解析过程完成后进行的,这确保了在defer脚本执行时,它们可以访问完整的DOM结构。因此,defer脚本虽然是HTML文档的一部分,但它们的执行是在文档解析后进行的,确保了DOM的完整性。


async

async属性意味着该脚本是完全独立的:

  • 浏览器不会阻止async脚本

  • 其他脚本也不会等待async脚本,async脚本也不会等待其他脚本

  • DOMContentLoadedasync 脚本不会互相等待

    • DOMContentLoaded可能在async脚本执行之前触发(如果async脚本在页面解析完成后完成加载)

    • 或在async脚本执行之后触发(如果async脚本很快加载完成或在 HTTP 缓存中)

简单来说就是 async 脚本在后台加载完就立即运行

应用场景:将独立的第三方脚本集成到页面中时,比如计数器,广告等。

Last updated