script标签 async 、defer区别
先上图:
1.普通的javascript
note:普通JS的下载和解析都会影响DOM解析
2.async
note:js的下载不影响DOM,执行影响DOM
在执行到加了async的script时会先下载,然后再去执行下一个标签。待到这个script的外链下载完毕时,如果DOM正在渲染则暂停,执行async script的内容。多个async先下载完的先执行
3.defer
note:js的下载不影响Dom的渲染和执行
在执行到加了defer的script时会推入下载进程,然后再去执行下一个标签。待到这个script的外链下载完毕时,需要看DOM是否渲染完毕了,如果渲染完毕了则执行defer script的内容,然后触发DOMContentLoaded 的回调。多个defer等待所有defer下载完依次执行。
什么时候适合用defer呢?
在这个JS对首屏渲染没任何影响时,加个defer标签可以把script放在任何位置不必担心影响首屏性能,根据m前面结论最好是在里。
常见的次屏渲染、打点JS、广告JS、推荐模块都可以用defer提升首屏打开性能。
有没有场景适合用 async 呢?
有,但很少。能用async的场景一定都是可以用defer的,但defer可能不是最优解。
设想所需的async script有可能因网速较慢耗时很长,那就比defer还要执行的靠后了。如果这种情况下出现大问题,那这个script根本就不适合使用async。async执行是无序的,如果无序没问题,那么defer的有序也一定没问题。
async完全被defer比下去了吗?不是的。由于async的自由性,他可以在首屏稳定后尽快的下载并执行对应的JS,这是defer做不到的。
例如首屏稳定后想更快的把PV打点发出去,这时候用async加载打点SDK并调用就很合适,虽然放在defer里也可以,但用户可能在defer执行前就退出了页面,打点就丢了,使用async更不容易丢打点(但退出过早,async也会丢打点)。
设想页面稳定后,还有100个毫不相关的script渲染100个模块,如使用defer,defer会在100个script下载完毕后才执行,用户如果已经开始翻动,则后面都是白屏,体验是较差的。这时改为async,用户在翻动时会看到最先渲染出来的异步模块,像极了懒加载,体验比defer更好些。