script标签中defer和async属性的区别
script标签中defer和async属性的区别
script标签存在两个属性,defer和async,因此script标签的使用分为三种情况:
1.
没有defer或async属性,浏览器会立即加载并执行相应的脚本。也就是说在渲染script标签之后的文档之前,不等待后续加载的文档元素,读到就开始加载和执行,此举会阻塞后续文档的加载;
①【如果放在head头里面引入,异步加载资源,但会阻塞的渲染,会出现白屏,按照顺序立即执行脚本】
②【如果放在body最下面的话:异步加载资源,等中的内容渲染完毕后且加载完按顺序执行JS】 相当于 用了defer
2.
有了async属性,表示后续文档的加载和渲染与js脚本的加载和执行是并行进行的,即异步执行;
[异步加载资源,且加载完JS资源立即执行,并不会按顺序,谁快谁先上]
3.
有了defer属性,[异步加载资源,在DOM渲染后之后再按顺序执行JS]
加载后续文档的过程和js脚本的加载(此时仅加载不执行)是并行进行的(异步),js脚本的执行需要等到文档所有元素解析完成之后,DOMContentLoaded事件触发执行之前。
【在这里我们可以明确DOMContentLoaded所计算的时间,当文档中没有脚本时,浏览器解析完文档便能触发 DOMContentLoaded 事件;如果文档中包含脚本,则脚本会阻塞文档的解析,而脚本需要等位于脚本前面的css加载完才能执行。在任何情况下,DOMContentLoaded 的触发不需要等待图片等其他资源加载完成。】
【页面上所有的资源(图片,音频,视频等)被加载以后才会触发load事件,简单来说,页面的load事件会在DOMContentLoaded被触发之后才触发。】
其中蓝色代表js脚本网络加载时间,红色代表js脚本执行时间,绿色代表html解析。
从图中我们可以明确一下几点:
1.defer和async在网络加载过程是一致的,都是异步执行的;
2.两者的区别在于脚本加载完成之后何时执行,可以看出defer更符合大多数场景对应用脚本加载和执行的要求;
3.如果存在多个有defer属性的脚本,那么它们是按照加载顺序执行脚本的;而对于async,它的加载和执行是紧紧挨着的,无论声明顺序如何,只要加载完成就立刻执行,它对于应用脚本用处不大,因为它完全不考虑依赖。
4.如果同时存在async 和 defer ,那么流程完全按照async走,defer 则不生效,不分添加的先后顺序~