搞懂script标签的defer和async

HTML5给<script>增加了两个布尔属性,deferasync,两者在使用上有点像又有点区别,很容易混淆。本文尝试理清之间的关系。

defer

defer script不会阻塞其他脚本的下载和HTML解析,但它会等到其他DOM构建完成才执行,然后才会触发DOMContentLoaded事件。也就是说,如果defer script下载得快,需要等一会(DOM构建完成)才执行。defer script有点像放在body最后面的script,但下载不受页面阻塞。

<!DOCTYPE html>
<head>
  <script src="/scripts/defer_script.js" defer></script>
</head>
<body>
  <!-- 10000项,HTML解析比较慢 -->
  {% for item in arr %}
  <p>Number {{ item }}</p>
  {% endfor %}
</body>
复制代码

defer_HFFS.jpg
defer script放在<head>里,HTML解析比较慢时,defer script下载完之后没有立即执行,而是等到document最后几个节点解析时才执行。

defer script会阻塞后面的defer script的执行,但不会阻塞后面的async script和普通script的执行。

<!DOCTYPE html>
<head>
  <script src="/scripts/defer_script1.js?t=50" defer></script>
  <script src="/scripts/defer_script2.js" defer></script>
</head>
<body>
  {% for item in arr %}
  <p>Number {{ item }}</p>
  {% endfor %}
</body>
复制代码

defer2_HFFS.jpg
defer_script1defer_script2之前,但是下载比较慢,最终依然是defer_script1先执行。

defer_script2的defer去掉或者改成async,都是defer_script2先执行。

async

async script的下载同样不会阻塞其他脚本的下载和HTML解析,但是执行会阻塞HTML解析。

想象这样的场景,async script下载很快,HTML解析速度一般,async script执行时间很长。可以看到,async script的执行阻塞了HTML解析。
HFSM.png
async script执行顺序不受前面的defer script或者async script影响,但会被前面的普通script的执行阻塞。

<!DOCTYPE html>
<head>
  <script src="/scripts/async_script2.js?t=50" async></script>
  <script src="/scripts/async_script1.js" async></script>
</head>
<body>
</body>
复制代码

async_multi_order.jpg
async_script2在document中位置比async_script1靠前,但由于网络请求会延时约50ms,最终执行也比async_script1晚。

结论

  1. 相同点
    1. 只用于外联script,<script>没有src属性时忽略该defer、async属性;
    2. script下载与HTML解析并行。
  2. 不同点
    1. defer script的执行在HTML解析完成之后,而async script的执行会阻塞HTML解析;
    2. 多个defer script的执行顺序与它们在document出现的顺序一致,async script的执行顺序依赖于它们下载完成的快慢。
    3. 同时使用deferasyncasync的优先级更高。

应用场景

  1. 像jquery之类的有依赖关系的script,建议使用defer,保证jquery执行完才执行其他三方脚本;
  2. 像数据埋点之类相对独立的script,建议使用async,但是要注意如果脚本下载得比较快,可能影响页面性能。

参考资料

  1. javascript.info/script-asyn…
  2. www.growingwiththeweb.com/2014/02/asy…
  3. www.digitalocean.com/community/t…

猜你喜欢

转载自juejin.im/post/7042889301553594398