defer
和async
是script
标签的两个属性,主要用于异步加载执行脚本,在不阻塞的页面文档解析前提下,控制脚本的下载和执行。
页面加载和渲染过程
- 浏览器通过
http
协议请求服务器,获取html
文档并开始从上到下解析,构建dom
- 在构建
dom
过程中,如果遇到html
文本里面引用外部资源链接,比如css、js
等,会立即启用别浏览器线程下载这些静态资源。需要注意的是,当遇到js
文件时,html
解析会停下来,等js
文件下载结束并执行完,html
解析工作才会继续。但是css
的加载并不会阻塞渲染过程,下载完成后会构建cssdom
- 完成文档解析后,将
dom
和cssdom
进行关联和映射,最后将视图渲染到浏览器窗口
script
我们需要注意的是当浏览器解析html
时,遇到script
引入外部js
时的集中不同情况。
<script src="index.js">
在讲解页面加载和渲染过程时,有说道js的加载解析执行都是同步的会阻塞渲染,指的就是默认情况下。没有defer
或async
浏览器会立即加载并执行指定的脚本,"立即"指的是在渲染该script
标签下的文档元素之前,也就是说不等待后续载入的文档元素,读到就加载并执行。
<script src="index" async>
有async
加载和渲染后续文档元素的过程和index.js
的加载并行进行(异步),当index.js
加载完毕后,会立即执行,如果这个时候html
没有解析完毕会阻塞html
解析,如果已经解析完毕,效果则与defer
相同
<script src="index" defer>
有defer
,加载后续文档元素的过程将和index.js
的加载并行执行(异步),但是index.js
的执行要在所有元素解析完成之后,DOMContentLoaded
事件触发之前完成。
加载执行时机的区别看图