defer和async是script标签的两个属性,用于在不阻塞页面文档解析的前提下,控制脚本的下载和执行。
先了解浏览器的加载和渲染过程:
- 浏览器先通过HTTP协议请求服务器,服务器响应浏览器获取HMTL文档并开始从上到下解析,构建DOM树;
- 在构建DOM树过程中,如果遇到外联的样式或脚本声明,会暂停HTML文档解析,创建新的网络连接,并开始下载样式文件和脚本文件;
- 样式文件下载完成后,构建CSSDOM;脚本文件下载完成后,解释并执行,然后继续解析文档构建DOM树。
-
完成文档解析后,将DOM和CSSDOM进行关联和映射,最后将视图渲染到浏览器窗口。
在这个过程中,脚本文件的下载会阻塞文档的解析,有时候会影响用户体验,所以就使用defer和async进行控制。
Paste_Image.png
1.当<script>没有任何属性。HTML文件在解析过程中遇到<script>标签,HTML的解析将停止,并将请求获取外部的js文件,并执行该脚本文件,执行完之后才继续解析html。
Paste_Image.png2.如果加了async <script async>,浏览器在HTML解析过程中下载js文件,js加载完之后暂停HTML解析器,并执行js,js执行完之后再继续解析HTML。也就是说加载和渲染后续文档的过程,与js文件的加载并行。
Paste_Image.png3.<script defer>
defer在HTML解析过程中下载js文件,只有解析完HTML后才执行该js文件。有defer的脚本可以按照它们在文档中出现的顺序执行。defer使加载后续文档元素的过程将和 js 的加载并行进行(异步),但js的执行要在所有元素解析完成之后。
有什么区别?
defer:
如果有多个声明了defer的脚本,则会按顺序下载和执行。
defer脚本会在DOMContentLoaded和load事件之前执行。
async:
如果有多个声明了async的脚本,其下载和执行也是异步的,不能确保彼此的先后顺序 .
async会在load事件之前执行,但并不能确保与DOMContentLoaded的执行先后顺序.
什么时候应该用什么?
如果脚本是模块化的,并且不依赖任何脚本,则使用async 。
如果脚本依赖或被另一个脚本依赖,那么使用defer 。
如果脚本很小并且被async脚本所依赖,那么使用在async脚本后面的内联脚本。
网友评论