@xiaoqq
2017-03-28T07:44:10.000000Z
字数 2814
阅读 2353
性能优化
使用网站:
参考文章:
浏览器JS执行规则是:“加载并行,执行串行”。
即脚本是同时加载,但是执行却是从上之下,依次执行。从某种程度上来说,这种做法是最高效地。

但是,通过Ajax的方式请求脚本,由于脚本大小、网络环境等不一,无法预知脚本返回的时间,导致脚本执行的时机并不一定。对于有依赖关系的脚本来说,脚本加载完成立即执行,显然是不合适。
所以,我们要提前确定脚本的加载顺序和依赖关系!
basket.js采用了promise的方式来解决脚本的依赖关系,比如underscore和backbone等jquery执行完成之后再请求:
basket.require({ url: 'test/fixtures/jquery.min.js' }).then(function () {basket.require({ url: 'test/fixtures/underscore-min.js' },{ url: 'test/fixtures/backbone-min.js' }).then(function () {var testModel = Backbone.Model.extend({idAttribute: '_id'});var myModel = new testModel({ _id: 4, name: 'Nyan Cat' });var message = $('#message');var templateContent = $('#intro').html();var compiled = _.template(templateContent);message.html(compiled({ name: myModel.get('name') }));});});
但是这样做存在一个很明显的问题:执行是串行了,但是加载也是串行的!这就很大程度上拖慢了网页初次加载的速度。

我能想到的最简单的方法是维护一个jsArr数组来保存每个脚本的信息,数组字段如下:
index: index, \\索引src: item, \\Urlcontent: "", \\脚本内容hasLoad: false,\\是否已加载hasEval: false \\是否已执行
每当从LS或者Ajax得到脚本的content时,就立即执行runJSArr方法:
function runJSArr() {for(var i=0; i<jsArr.length; i++) {var item = jsArr[i];//如果之前有脚本未加载完成,则返回if(!item.hasLoad) {return;}else {if(!item.hasEval) {console.debug("[casket]\t"+item.src+"\teval complete");window.eval(item.content);item.hasEval = true;if(i == jsArr.length-1) {var endTime = performance.now();var costTime = (endTime-startTime).toFixed(2)console.debug("[casket]\tall eval complete; cost time: "+costTime+"ms; total count: "+jsArr.length);}}}}}
规则如下:
1. 从前至后,依次遍历jsArr数组;
2. 如果脚本标记为未加载完成,则立即返回;
3. 如果脚本已完成,则判断脚本是否已执行,如果脚本已执行,则跳过,如果未执行,则使用eval方式执行脚本;

浏览器的缓存分为两种:强缓存和协商缓存(304);关于两种缓存的比较可以参考:http://mp.weixin.qq.com/s?__biz=MzAxODE2MjM1MA==&mid=2651551769&idx=1&sn=3a422455b5cc240f8625842d31d81ab8&chksm=8025afd8b75226cec68e1e0e4b36334bb1d88e51a7fdba0cf7884d9f1d6597e4e4475cffaa38&mpshare=1&scene=1&srcid=03276TwHFG2sTfSMyrFf2Hji#rd
为了比较LocalStorage缓存的性能与原生缓存方案的性能对比,我们做了如下的测试:

结论是:LocalStorage缓存的性能与强缓存相当,远远强于不缓存的情况。