看一下这张图,已经说明了普通 script,async 和 defer。
普通 script
一个普通的 script 标签如下:
<script src="foo.js"></script>
当解析 HTML 遇到 <script>
的时候:
- 停止解析;
- 请求下载
foo.js
(如果它是外部引入的,不是内联脚本内联脚本) ; - 执行
foo.js
; - 执行完成之后,继续解析 HTML
async
<script src="foo.js" async></script>
添加 async
之后,解析遇到这个 <script>
时:
- 并行的请求下载
foo.js
,不停止解析; - 下载完成之后,停止解析,立即执行下载的脚本;
- 执行完成之后,继续解析。
值得注意的是,async
脚本会在脚本加载后立即执行,因此不能保证执行顺序(最后包含的脚本可能会在第一个脚本文件之前执行)。
defer
<script src="foo.js" defer></script>
添加 defer
之后,解析遇到这个 <script>
时:
- 并行的请求下载
foo.js
,不停止解析; - 只有解析完成之后,在
DOMContentLoaded
实践前执行。
与 async
不同,defer
保证按照它们在页面中出现的顺序执行。
总结
- async 会阻止 document 的解析;
- defer 会在 DOMContentLoaded 前依次执行;
- async 则是下载完立即执行,不一定是在 DOMContentLoaded 前;
- async 因为顺序无关,所以很适合像 Google Analytics 这样的无依赖脚本;