blog icon indicating copy to clipboard operation
blog copied to clipboard

彻底搞懂 async & defer

Open xiaoyu2er opened this issue 7 years ago • 11 comments

彻底搞懂 async & defer

TL;DR

两者都会并行下载,不会影响页面的解析。

defer 会按照顺序在 DOMContentLoaded 前按照页面出现顺序依次执行。

async 则是下载完立即执行。

兼容性

普通 script

先来看一个普通的 script 标签。

<script src="a.js"></script>

浏览器会做如下处理

  • 停止解析 document.
  • 请求 a.js
  • 执行 a.js 中的脚本
  • 继续解析 document

defer

<script src="d.js" defer></script>
<script src="e.js" defer></script>
  • 不阻止解析 document, 并行下载 d.js, e.js
  • 即使下载完 d.js, e.js 仍继续解析 document
  • 按照页面中出现的顺序,在其他同步脚本执行后,DOMContentLoaded 事件前 依次执行 d.js, e.js。

async

<script src="b.js" async></script>
<script src="c.js" async></script>
  • 不阻止解析 document, 并行下载 b.js, c.js
  • 当脚本下载完后立即执行。(两者执行顺序不确定,执行阶段不确定,可能在 DOMContentLoaded 事件前或者后 )

其他

  • 如果 script 无 src 属性,则 defer, async 会被忽略
  • 动态添加的 script 标签隐含 async 属性。

结论

  • 两者都不会阻止 document 的解析
  • defer 会在 DOMContentLoaded 前依次执行 (可以利用这两点哦!)
  • async 则是下载完立即执行,不一定是在 DOMContentLoaded 前
  • async 因为顺序无关,所以很适合像 Google Analytics 这样的无依赖脚本

Reference

xiaoyu2er avatar Mar 12 '17 15:03 xiaoyu2er

两者都不会阻止 document 的解析 defer 会在 DOMContentLoaded 前依次执行 (可以利用这两点哦!) async 则是下载完立即执行,不一定是在 DOMContentLoaded 前 async 因为顺序无关,所以很适合像 Google Analytics 这样的无依赖脚本

Thinking80s avatar Mar 18 '17 06:03 Thinking80s

那是否认为 defer 可以替代普通的 script 标签?

quanru avatar May 20 '18 09:05 quanru

@quanru 不可以啊 因为有可能 js 会修改 dom 啊

xiaoyu2er avatar May 21 '18 13:05 xiaoyu2er

@xiaoyu2er 受教了~

quanru avatar May 21 '18 14:05 quanru

@quanru 不可以啊 因为有可能 js 会修改 dom 啊

普通script标签内有js,带defer的script标签内也有js,都有可能修改DOM。在修改dom这点上,怎么论证“defer不能替代普通的script标签”呢?

zhenmang avatar Sep 23 '18 04:09 zhenmang

赞 多谢分享

icantunderstand avatar Oct 25 '18 02:10 icantunderstand

<script src="script.js"></script>

没有 defer 或 async,浏览器会立即加载并执行指定的脚本,“立即”指的是在渲染该 script 标签之下的文档元素之前,也就是说不等待后续载入的文档元素,读到就加载并执行。

<script async src="script.js"></script>

有 async,加载和渲染后续文档元素的过程将和 script.js 的加载与执行并行进行(异步)。

<script defer src="myscript.js"></script>

有 defer,加载后续文档元素的过程将和 script.js 的加载并行进行(异步),但是 script.js 的执行要在所有元素解析完成之后,DOMContentLoaded 事件触发之前完成。

beinimaliesi avatar Jan 24 '19 06:01 beinimaliesi

async会阻止DOM parase

https://i.stack.imgur.com/wfL82.png

jparser avatar Feb 12 '19 08:02 jparser

Defer 会阻止DOM parase

https://i.stack.imgur.com/wfL82.png

你这图是async运行时会HTML parsing paused,defer不会

Archao-ME avatar Mar 07 '19 06:03 Archao-ME

Defer 会阻止DOM parase https://i.stack.imgur.com/wfL82.png

你这图是async运行时会HTML parsing paused,defer不会

他本来说的就是async会阻塞HTML解析,可作者说的是两者都不会阻塞HTML解析,明显是错误的。

zhixinpeng avatar Sep 24 '19 01:09 zhixinpeng

Defer 会阻止DOM parase https://i.stack.imgur.com/wfL82.png

你这图是async运行时会HTML parsing paused,defer不会

他本来说的就是async会阻塞HTML解析,可作者说的是两者都不会阻塞HTML解析,明显是错误的。

下载的时候不阻塞,执行的时候阻塞。

ibufu avatar Jul 23 '20 10:07 ibufu