[关闭]
@xiaoqq 2017-03-28T07:44:10.000000Z 字数 2814 阅读 2045

使用localStorage离线缓存静态资源

性能优化


一、 引言

  1. 参考项目:
  2. 使用网站:

  3. 参考文章:

  4. 学术论文:
    • 基于Web前端的localStorage性能研究与改进

二、localstorage简介

三、localstorage离线缓存的优势

  1. 减小总页面的大小
  2. localstorage加载脚本速度比本地缓存更快
    据研究,LocalStorage缓存的速度比本地缓存的速度快5倍[1]

    20% trimmed mean results of native browser cache vs localStorage performance. Mean performance for localStorage is always faster than the browser's native cache and for iOS 5 & 6, dramatically so.
  3. 减小请求个数
    浏览器的并发个数是有限的,超过并发上限的资源就需要等待之前的资源下载完毕,这就大大延迟了页面的加载时间。

四、脚本加载和执行规则

浏览器JS执行规则是:“加载并行,执行串行”
即脚本是同时加载,但是执行却是从上之下,依次执行。从某种程度上来说,这种做法是最高效地。

但是,通过Ajax的方式请求脚本,由于脚本大小、网络环境等不一,无法预知脚本返回的时间,导致脚本执行的时机并不一定。对于有依赖关系的脚本来说,脚本加载完成立即执行,显然是不合适。

所以,我们要提前确定脚本的加载顺序和依赖关系!

basket.js采用了promise的方式来解决脚本的依赖关系,比如underscore和backbone等jquery执行完成之后再请求:

  1. basket
  2. .require({ url: 'test/fixtures/jquery.min.js' })
  3. .then(function () {
  4. basket
  5. .require(
  6. { url: 'test/fixtures/underscore-min.js' },
  7. { url: 'test/fixtures/backbone-min.js' }
  8. )
  9. .then(function () {
  10. var testModel = Backbone.Model.extend({
  11. idAttribute: '_id'
  12. });
  13. var myModel = new testModel({ _id: 4, name: 'Nyan Cat' });
  14. var message = $('#message');
  15. var templateContent = $('#intro').html();
  16. var compiled = _.template(templateContent);
  17. message.html(compiled({ name: myModel.get('name') }));
  18. });
  19. });

但是这样做存在一个很明显的问题:执行是串行了,但是加载也是串行的!这就很大程度上拖慢了网页初次加载的速度。

我能想到的最简单的方法是维护一个jsArr数组来保存每个脚本的信息,数组字段如下:

  1. index: index, \\索引
  2. src: item, \\Url
  3. content: "", \\脚本内容
  4. hasLoad: false,\\是否已加载
  5. hasEval: false \\是否已执行

每当从LS或者Ajax得到脚本的content时,就立即执行runJSArr方法:

  1. function runJSArr() {
  2. for(var i=0; i<jsArr.length; i++) {
  3. var item = jsArr[i];
  4. //如果之前有脚本未加载完成,则返回
  5. if(!item.hasLoad) {
  6. return;
  7. }else {
  8. if(!item.hasEval) {
  9. console.debug("[casket]\t"+item.src+"\teval complete");
  10. window.eval(item.content);
  11. item.hasEval = true;
  12. if(i == jsArr.length-1) {
  13. var endTime = performance.now();
  14. var costTime = (endTime-startTime).toFixed(2)
  15. console.debug("[casket]\tall eval complete; cost time: "+costTime+"ms; total count: "+jsArr.length);
  16. }
  17. }
  18. }
  19. }
  20. }

规则如下:
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缓存的性能与强缓存相当,远远强于不缓存的情况。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注