前端性能优化篇之异步加载js文件

论坛 期权论坛 期权     
鸭梨web前端   2019-6-29 21:29   2541   0
浏览器加载 JavaScript 脚本,主要通过元素完成。加载外部脚本时 浏览器会暂停页面渲染,等待脚本下载并执行完成后,再继续渲染。因此当js脚本数量比较多,并且都是同步加载时,就很容易造成页面加载时间过长,性能差的表现;
v2-757212b6ecac206528be7c3e7e0ed135_1200x500.jpg
  • 异步加载又叫非阻塞加载,浏览器在下载执行js的同时,还会继续进行后续页面的处理。
[h1]异步加载js的几种方式[/h1]
  • async 方式
  • defer 方式
  • 动态创建 script 标签
[h1]1、defer 属性[/h1]
  • defer属性在IE4.0就出现了。
  • defer属声明脚本中将不会有document.write和dom修改。
  • 浏览器会并行下载其他有defer属性的script,在HTML解析完之后才会执行下载好的脚本,不会阻塞页面后续处理。
  • defer脚会按照加载顺序执行的。
如果脚本不会改变文档的内容,可将 defer 属性加入到 script 标签中,以便加快处理文档的速度。
通过给
  1. [/code]标签设置[code]defer
复制代码
属性,将脚本文件设置为延迟加载,当浏览器遇到带有
  1. defer
复制代码
属性的
  1. [/code]标签时,会再开启一个线程去下载[code]js
复制代码
文件,同时继续解析
  1. HTML
复制代码
文档,等
  1. HTML
复制代码
全部解析完毕
  1. DOM
复制代码
加载完成之后,再去执行加载好的
  1. js
复制代码
文件。这种方式只适用于引用
  1. 外部js文件的标签
复制代码
,如果是多个脚本,该方法可以确保所有设置了 defer 属性的脚本按引入顺序执行,但是要注意,添加defer属性的js文件不应该使用document.write方法。
复制代码
[h1]2、async 方式[/h1]
  • async 属性是 HTML5 新增属性,需要 Chrome、FireFox、IE9+ 浏览器支持,
  • async 属性加载完之后立即执行,如果是多个,执行顺序和加载顺序无关
  • async 属性仅适用于外部脚本
  • 如果是多个脚本,该方法不能保证脚本按顺序执行
  1. async
复制代码
属性和
  1. defer
复制代码
属性类似,也是会开启一个线程去下载js文件,但和
  1. defer
复制代码
不同的时,它会在
  1. 下载完成后立刻执行
复制代码
,而不是会等到DOM加载完成之后再执行,所以还是有
  1. 可能会造成阻塞
复制代码

同样的,
  1. async也是只适用于外部js文件
复制代码
,也不能在js中使用document.write方法,但是
  1. 对多个带有async的js文件,它不能像defer那样保证按顺序执行
复制代码
,它是哪个js文件先下载完就先执行哪个。
  1. [/code][h1]3、 动态创建 script 标签[/h1][code](function(){    var scriptEle = document.createElement("script");    scriptEle.type = "text/javasctipt";    scriptEle.async = true;    scriptEle.src = "http://cdn.bootcss.com/jquery/3.0.0-beta1/jquery.min.js";    var x = document.getElementsByTagName("head")[0];    x.insertBefore(scriptEle, x.firstChild); })();
复制代码
  1. (function(){    if(window.attachEvent){        window.attachEvent("load", asyncLoad);    }else{        window.addEventListener("load", asyncLoad);    }    var asyncLoad = function(){    var ga = document.createElement('script');    ga.type = 'text/javascript';    ga.async = true;    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';    var s = document.getElementsByTagName('script')[0];    s.parentNode.insertBefore(ga, s);    }})();
复制代码
上面两种方法中,第一种方式执行完之前会阻止onload事件的触发,而现在很多页面的代码都在onload时还执行额外的渲染工作,所以还是会阻塞部分页面的初始化处理。第二种则不会阻止onload事件的触发。
这里要简要说明一下window.DOMContentLoaded和window.onload这两个事件的区别,前者是在DOM解析完毕之后触发,这时候DOM解析完毕,JavaScript可以获取到DOM引用,但是页面中的一些资源比如图片、视频等还没有加载完,作用同jQuery中的ready事件。后者则是页面完全加载完毕,包括各种资源。
[h2]什么时候用defer,什么时候用async呢?[/h2]
一般来说,两者之间的选择则是
  1. 看脚本之间是否有依赖关系
复制代码
,有依赖的话应当要保证执行顺序,应当使用defer没有依赖的话使用async,同时使用的话defer失效。要注意的是两者
  1. 都不应该使用document.write
复制代码
,这个导致整个页面被清除。
参考:
  • https://mp.weixin.qq.com/s/MDk7aSAECMF_e4I39EwA9w
  • https://juejin.im/post/5bcdaed7e51d457a8254e1b7
  • https://blog.csdn.net/weixin_39805338/article/details/80770098

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:
帖子:
精华:
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP