侧边栏壁纸

script标签中的defer和async可提高网页加载速度

2024年04月23日 360阅读 0评论 1点赞


普通script:

1.文档解析的过程中,如果遇到script脚本, 停止页面的解析渲染, 下载script脚本。
2.如果是多个script脚本, 近似于同时并行下载script脚本。(虽然说是遇到script脚本, 就停止后面标签的解析渲染; 但chrome做了优化, 遇到script脚本, 会快速的查看后边有没有需要下载其他资源的, 一起并行下载, 为了节省一部分下载的时间。 )
3.不论script脚本哪个先下载好, 都按照html中的先后顺序依此执行。 即如果后面的script脚本先下载好, 要等前面的script脚本下载好并执行后, 才能执行。
4.执行script脚本时, 也是停止页面的解析渲染。
5.执行完script脚本, 继续页面的解析渲染。
6.执行完script脚本和页面解析渲染完, 才会依此触发DOMContentLoaded, loaded事件

总结:

普通script的 下载和执行 都阻塞页面的解析渲染。
多个script的下载是并行, 但按照页面中顺序依此执行。
考虑到不支持defer和async的老浏览器, 最佳实践是script放在body底部, 避免阻塞页面的解析渲染。
执行完script脚本, 继续页面的解析渲染。页面解析渲染完, 才会触发DOMContentLoaded。所以普通script脚本的下载和执行如果慢, 会延迟DOMContentLoaded事件的触发时间。

defer:

文档解析时,遇到设置了defer的script脚本,就会在后台进行下载,下载并不会阻止文档的解析渲染。
如果是多个设置了defer的script脚本, 近似于同时并行下载defer脚本。
当页面解析渲染完毕后, 会等到所有的defer脚本下载完毕并按照顺序执行,执行完毕后会触发DOMContentLoaded事件。
如果defer脚本下载较快, 会等到页面解析渲染完毕后, 才按照顺序执行defer脚本。执行完毕后会触发DOMContentLoaded事件。
如果defer脚本下载较慢, 在下载完前, 页面解析渲染已完毕; 等defer脚本下载完后, 才按照顺序执行defer脚本。执行完毕后会触发DOMContentLoaded事件。

总结:

defer脚本的 下载和执行 都不会阻塞页面的解析渲染。因为等到页面的解析渲染完毕后, defer脚本才执行, 所以defer脚本执行 也不会阻塞页面的解析渲染。
多个defer脚本的下载是并行, 但按照顺序依此执行。
等页面的解析渲染完毕后, 触发DOMContentLoaded事件前, defer脚本才依次执行。 所以defer脚本的下载和执行如果慢, 会延迟DOMContentLoaded事件的触发时间。
考虑有的浏览器不支持 defer场景, 多个defer脚本不一定会按照顺序执行, 最佳实践是只使用一个defer脚本。
推荐场景:
如果你的脚本代码依赖于页面中的DOM元素(文档是否解析完毕),或者被其他脚本文件依赖。

例:

评论框
代码语法高亮
polyfill.js

async:

文档解析时,遇到设置了async的script脚本,就会在后台进行下载,下载并不会阻止文档的解析渲染。
如果是多个设置了async的script脚本, 近似于同时并行下载async脚本。
async脚本的执行会阻止文档的解析渲染。
哪个async脚本先下载完, 就立刻执行, 执行时阻止文档的解析渲染。async脚本执行顺序不按照页面中的脚本先后顺序。
async脚本的下载和执行不计入DOMContentLoaded事件统计。
因async脚本下载不阻塞文档的解析渲染; 如果async脚本下载较快, 趁async脚本下载很短时间内, 文档的解析渲染未完成, async下载后立即执行, 执行时会阻塞文档的解析渲染; 执行后, 继续文档的解析渲染, 等页面的解析渲染完毕后, 触发DOMContentLoaded事件。这种场景, async脚本的执行如果慢, 会延迟DOMContentLoaded事件的触发时间。
如果async脚本下载较慢, 当async还在下载时, 文档的解析渲染已完成, 这时不会等待async的下载, 会直接触发DOMContentLoaded事件。这种场景, async脚本的下载和执行不会延迟DOMContentLoaded事件的触发时间。

总结:

async脚本的 下载 不会阻塞页面的解析渲染。async脚本的 执行 会阻塞页面的解析渲染。

多个async脚本的下载是并行, 但执行不按照页面中的脚本先后顺序。哪个async脚本先下载完, 哪个async脚本就先立刻执行。
async脚本的下载和执行不计入DOMContentLoaded事件统计。
async脚本的执行有可能在 DOMContentLoaded 事件前, 也有可能在 DOMContentLoaded 事件后。
当async脚本的执行在 DOMContentLoaded 事件前时, async脚本的执行时间才会影响DOMContentLoaded事件的触发时间。又因为脚本的执行时间一般都比较短, 所以可以认为async脚本基本不影响DOMContentLoaded事件的触发时间。

推荐场景:

如果你的脚本并不关心页面中的DOM元素(文档是否解析完毕),并且也不会产生其他脚本需要的数据。

例:百度统计和Google Analytics

普通script, defer, async同时存在页面中:

普通script执行完, 继续页面解析渲染; 页面解析渲染完, 才触发DOMContentLoaded事件。
defer脚本是在页面解析渲染完, DOMContentLoaded事件的触发前, 才执行defer脚本。
由于1,2这两点, 所以一定先执行普通script, 再执行defer脚本。
async脚本的下载和执行不计入DOMContentLoaded事件统计。
async脚本下载完, 就立刻执行, 且多个async脚本执行不按照页面中的脚本先后顺序。
由于4,5这两点, 所以async脚本执行与普通script, defer脚本无关, 那个时间点都有可能执行。

简述:

defer和async都是用于优化脚本加载和执行的属性,它们可以帮助提高网页加载速度。

dasync属性:

当浏览器遇到带有async属性的<script>标签时,它会异步下载该脚本文件,并且不会等待脚本下载和执行,而是继续解析和加载页面。
一旦脚本下载完成,它会立即执行,执行时机可能在页面其他部分加载之前或之后,取决于脚本文件的下载速度和执行时间。
这种方式适用于对页面其他部分没有依赖关系的脚本,因为它们可能会在 DOMContentLoaded 事件触发之前或之后执行,可能会影响到页面的渲染。

defer属性:

与async不同,带有defer属性的脚本会在文档解析完毕后,DOMContentLoaded 事件触发之前依次执行,保证了脚本的执行顺序与它们在页面中出现的顺序一致。
浏览器会异步下载带有defer属性的脚本文件,但会等到文档解析完毕后再按照顺序执行。
这种方式适用于对页面其他部分有依赖关系的脚本,因为它们保证在 DOMContentLoaded 事件触发之前执行,可以确保脚本在文档完全加载后再执行。
原理上,这两种属性都能够提高页面加载速度,因为它们允许浏览器异步下载脚本文件,不会阻塞页面的加载和渲染。但需要注意的是,它们的使用场景和行为略有不同,需要根据具体情况选择合适的属性来优化脚本加载。

1
打赏

—— 评论区 ——

昵称
邮箱
网址
取消
舔狗日记