@xiaoqq
2017-03-28T07:44:10.000000Z
字数 2814
阅读 2045
性能优化
使用网站:
参考文章:
浏览器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, \\Url
content: "", \\脚本内容
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缓存的性能与强缓存相当,远远强于不缓存的情况。