离线缓存方案

在 webapp 开发中,数据存储和离线可访问是每个开发者遇到的难题,也是影响用户体验的主要一环;为了克服缺陷,HTML不断推出新接口,从Cookie延续到 localStorage、 Web SQL DataBase和AppCache,但现存的接口依然存成如下问题:

1. 存储量有限,存储形式太过单一;

cookie存储数量和大小都有所限制,存储形式上按照字符串进行拼接; 新推出的localStorage对cookie有很好补充作用,提供key-value键值对存储,但大小依然受限,不提供结构化存储;

2. 系统支持程度不统一,无法保证成功率;

android分支越来越多,对应的web api支持情况也更加多样;如对结构化存储支持很好的indexedDB接口,必须运行在android大于4.3,ios大于8.1的版本;接口支持的不统一,很难保证成功率;

3. 无法满足对文件内容的存储和获取;

现在还没有接口可以读取和存储文件, 为了保证离线可访问必须对文件内容进行存取;

4. 无法实时更新,最终结果无法预料;

页面采用Cache Manifest可实现页面离线可访问, 但用户无法实时更新,内容更新之后须修改配置文件当用户第二次刷新时可看到新的内容;

5. 接口使用太过复杂,各个接口互相孤立;

保证webapp离线可访问是个系统工程,牵涉到存储、网络检测、文件读取、安全等,现存的接口是不同时期推出,每个接口仅是为了解决局部问题引入,没有系统性的集合起来供用户使用;

从分析情况来看,依靠纯web提供的接口无法完全满足需求,百度Clouda+近期1.2版本发布,提供了另一种离线缓存方案;

Clouda+离线方案

通过分析web提供的api,须在自己控制的系统中设计一套独立的API,需要有下面几个模块:

  1. 存储模块

    为了提高检索速度,支持结构化存储和索引查询数据;因要存储大量静态资源文件,存储大小应该不受限制;

  2. 网络模块

    此模块内可以拦截网络请求,对拦截的请求内容存储到本地,保证离线时获取;还可以对网络情况进行判断,使其从不同渠道获取内容;

  3. 文件模块

    拦截了请求之后,下一步就必须把此请求的文件内容进行存储或者读取,文件I/O操作必不可少;

  4. 安全模块

    数据下载到了手机空间中,必须对文件进行安全加密和访问限制,保证数据安全

Clouda+的Runtime提供了webapp运行环境,此方案设计也架构在了Runtime之中,下面是其架构图: clipboard

网络拦截和网络环境模块提供网络接口,通过对网络环境的判断来确定是否拦截网络请求;数据存储模块是个精简的数据库系统,用户可存储或者索引数据;文件存储提供了对文件的下载和读取;访问策略和安全加密提供了安全模块,来限制文件的自由读取;

方案优势

1. 存储量不再受限制;

存储量仅和用户手机空间大小相关;

2. 支持了文件下载和读取;

通过对文件下载和读取接口,用户可以把图片、页面内容或者数据等方便下载到手机空间中,突破web无法操作文件的限制;

3. 不受手机自身webview版本的限制;

Clouda+的数据或者文件存储都是依靠框架自身能力实现,不依赖手机本身,也就是只要升级到Clouda+最新版本,都完美支持此功能;

4. 离线访问可自由控制,保证实时性和离线可访问性;

Clouda+设置了拦截器开关,可自由拦截网络资源,是否用离线数据用户可自由控制;

5. 对接口就行了整合封装,几乎可零配置支持网络资源离线访问;

Clouda+对各个接口基础上进行了封装,用户几乎零配置就可以让其webapp支持离线访问;

如何使用

使用Clouda+离线缓存技术必须在其提供的Runtime环境下进行开发, 引入clouda+入口脚本文件loader;提供了智能的离线缓存和主动调用方式:

智能化配置

1. 首页载入cache模块且进行初始化;
Blend.lightInit({
    ak:  'xxxxxxxxxx', // 百度开发者平台提供的appKey
    module: ['cache']
},  function(){
    Blend.device.cache.init();// 加载完成后初始化
});
2. 页面head头部引入meta标签,配置需要缓存的资源;

如自动缓存图片资源侧添加如下:

<meta name="Cache-Type" content='image/gif,image/png', image/jpg />

添加完之后,不需要任何代码,webapp就可以对图片资源进行了拦截,离线时候就可适用缓存资源;

主动调用

1. 首先载入cache模块;
Blend.lightInit({
    ak:  'xxxxxxxxxx', // 百度开发者平台提供的appKey
    module: ['cache']
});
2. 调用set缓存相应资源
Blend.device.cache.set({
    url:'xxxxxxxxxxxxxx', // 要离线的资源文件
    onsuccess: function( data ){
        //成功回调
    },
    onfail: function(){data}{
        // 失败回调
    }
});

回调中可传入参数filedata,告诉拦截器什么网络环境下进行读取缓存资源;

3. 打开拦截器
Blend.device.interceptor.set({
    status: 1, // 1打开,0 关闭
    onsuccess: function( data ){
        //成功回调
    },
    onfail: function(){data}{
        // 失败回调
    }
});

之后再次请求缓存的资源地址,拦截器根据网络环境和配置,自动判断获取缓存或者线上拉取;

以上只是智能离线缓存使用方法,此次升级把所依赖的底层接口fs、 database、connection、interceptor都已开放,可在此基础上延伸出更多技术方案。