使用defer或async加载脚本

使用script的defer或async属性, 加载外部脚本的script标签就可以不用放在body的底部了

defer

defer兼容性

IE6~9可以用, 但有点小问题; IE10+, 移动端放心用

IE6~9的小问题: 使用defer后的script标签的执行顺序得不到保证
如果类库间相互依赖, 如需要先加载jQuery再加载jQuery-ui, 则IE6~9不能使用defer

async

async兼容性

IE10+, 移动端放心用

区别

  • 执行顺序

defer是有顺序保证的, 两个script标签都有defer属性, 则先执行第一个, 再执行第二个

async是无顺序保证的, 两个script标签都有async属性, 则哪个先加载完成就先执行哪个

  • 执行时机

defer在html解析完成后, DOMContentLoaded之前执行js

async在加载完js后就会执行, 最迟也必须在window.onload事件之前

注意

  • defer与async都只对外链js有效, 即只对含有src属性的script标签有效

  • 如果同时script标签同时有defer与async属性, 则以aysnc为准; 当浏览器不支持async时, 再回退使用defer属性, 这相当于是一个兼容措施

结论

  • 对于不依赖DOM构建完成, 并且与首页渲染无关的脚本, 可以使用aysnc; 考虑兼容IE6~9的话, 可以使用async+defer来做fallback

  • 对于依赖DOM构建完成的脚本, 可以使用defer, 不过要注意IE6~9不能保证顺序的bug

  • 如果页面是由js类库(如React)构建的, 则最好让相关构建页面的js成为inline sciprt, 内嵌到html中, 减少网络请求等待的时间

  • 最后, 如果考虑兼容IE9的话, script标签还是放在body底部更妥😑

参考资料

defer-issue
running-scripts-in-webkit
script-with-defer-and-async
inlining-JavaScript-if-use-framework-to-construct-the-page

Fork me on GitHub