1.为什么要使用defer和async
script标签用于加载脚本与执行脚本,是前端开发中非常重要的标签
直接使用script脚本的话,html会按照顺序来加载并执行脚本,在脚本加载及执行分过程中,会阻塞后续的DOM渲染.
现在script提供了async和defer两个属性来解决DOM渲染阻塞的问题
2.async
<script async src="script.js"></script>
有 async,加载和渲染后续文档元素的过程将和 script.js 的加载与执行并行进行(异步)。
异步脚本不能保证按照它们在页面中出现的次序执行。
3.defer
<script defer src="script.js"></script>
有 defer,加载后续文档元素的过程将和 script.js 的加载并行进行(异步),
但是 script.js 的执行要在所有元素解析完成之后,DOMContentLoaded 事件触发之前完成。
推迟的脚本原则上按照它们被列出的次序执行。
4.区别
1.没有defer和async的时候浏览器会立即加载JS文件并执行指定的脚本,“立即”指的是在渲染该 script 标签
之下的文档元素之前,也就是说不等待后续载入的文档元素,读到就加载并执行。
2.有 async,加载和渲染后续文档元素的过程将和 script.js 的加载与执行并行进行(异步)。
当JS加载完成,JS代码立即执行,会阻塞HTML渲染。
但与defer不同的是,标记为async的脚本并不保证按照它们的先后顺序执行。
3.加上defer,加载后续文档元素的过程将和 script.js 的加载并行进行(异步),
当HTML渲染完成,才会执行JS代码。
5.渲染阻塞的原因
由于 JavaScript 是可操纵 DOM 的,如果在修改这些元素属性同时渲染界面(即 JavaScript 线程和 UI 线
程同时运行),那么渲染线程前后获得的元素数据就可能不一致了。因此为了防止渲染出现不可预期的结果,浏览
器设置 GUI 渲染线程与 JavaScript 引擎为互斥的关系。当浏览器在执行 JavaScript 程序的时候,GUI 渲
染线程会被保存在一个队列中,直到 JS 程序执行完成,才会接着执行。如果 JS 执行的时间过长,这样就会造成
页面的渲染不连贯,导致页面渲染加载阻塞的感觉