当浏览器碰到 script 脚本的时候:
- 不使用
defer
和async
<script src="script.js"></...>
浏览器会立即加载并执行指定的脚本,“立即”指的是在渲染该 script 标签之下的文档元素之前,不等待后续载入的文档元素(即会暂停渲染页面),读到就加载并执行。
- 使用
async
<script async src="script.js"></...>
加载和渲染后续文档元素的过程将和 script.js
的加载与执行并行进行(异步)。
- 使用
defer
<script defer src="script.js"></...>
加载后续文档元素的过程将和 script.js
的加载并行进行(异步),但是 script.js
的执行要在所有元素解析完成之后,DOMContentLoaded
事件触发之前完成。
从实用角度来说呢,首先把所有脚本都丢到 body
闭合标签之前是最佳实践,因为对于旧浏览器来说这是唯一的优化选择,此法可保证非脚本的其他一切元素能够以最快的速度得到加载和解析。
PS:浏览器支持并行加载静态文件(如图片、css文件、js文件),但是有限制,比如Chorme在HTTP 1.1协议下,只支持最多6个文件并行加载。
接着,我们来看一张图,其中绿色线代表 HTML 解析,蓝色线代表网络读取,红色线代表执行时间:
)
由此可以得出async
和defer
的区别在于:
defer
和async
在网络读取(下载)文件时相对于HTML解析都是异步的defer
在文档解析完成后再执行JS脚本(按顺序执行)async
会在加载完成后立即执行(先加载完成则先执行,无序执行)