【转】基于localStorage的资源离线和更新技术

ServiceWorker的资源离线与更新

ServiceWorker是替代Application Cache的机制,目前为止其兼容性很差。

localStorage资源离线缓存与更新

基本思路:将JavaScript、CSS资源文件甚至是接口返回的数据资源缓存到浏览器的localStorage中,下次打开页面时不进行JavaScript、CSS资源的请求,而是直接通过localStorage读取内容,然后插入到页面中解析执行。

HTML

<div id="versionStore" data-version="2"></div>

JS

/**
 * localStorage方式实现增量更新
 */
let localStorage = window.localStorage,
    oldVersion = localStorage.getItem(‘version‘) || 0,  // version记录localStorage中存的版本
    newVersion = +document.querySelector(‘#versionStore‘).getAttribute(‘data-version‘);  // 当前最新版本

let content = null;
if(newVersion > oldVersion) {
    // 内容有更新或第一次加载
    const xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function(event){
        if (xhr.readyState == 4){
            if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
                content = xhr.responseText;
                updateScript(content); // 更新脚本
                localStorage.setItem(‘version‘, newVersion); // 更新本地版本
                localStorage.setItem(‘a.js‘, content); // 更新本地内容

            }
        }
    };
    xhr.open("get", "index.js", true);
    xhr.send(null);
} else {
    // 无内容更新
    content = localStorage.getItem(‘a.js‘); // 直接获取本地内容
    updateScript(content)
}

/**
 * 更新页面脚本
 * @param content 脚本内容
 */
function updateScript(content) {
    let script = document.createElement(‘script‘);
    script.innerHTML = content;
    document.body.appendChild(script);
    script = null;
}

  页面脚本通过获取页面上的“最新版本号”和本地localStorage保存的“旧版本号”进行对比。如果本地没有版本号或者版本号较旧,则加载最新版本的静态资源文件到页面上,同时更新本地原有的localStorage缓存的内容和版本号;否则直接读取localStorage的静态资源内容到页面中解析执行。

缺点:(1)localStorage的大小限制,同域下一般是5MB;(2)用户手动清空localStorage会使离线资源失效;(3)读取localStorage的速度比较慢,尤其是移动端。

基于增量文件的更新方式

如果一个文件中只修改了少量字符,上述方式会导致整个资源文件的更新。为了节省流量我们需要增量更新。假设我们已有1.1,1.2,1.3三个版本发布,现在需要进行1.4的发布上线。为了满足增量更新,我们需要根据前面的三个版本文件内容与最新版本内容进行对比分析,分别生成三个不同版本的增量文件1.1-1.4.js,1.2-1.4.js,1.3-1.4.js,同时保留1.4版本的全量文件。

// 实现方式跟上述类似,只需修改请求地址
xhr.open("get", `${oldVersion}-${newVersion}.js`, true);

 

基于文件代码分块的增量更新机制

根据大小确定分割字符数(比如10个字符),文件字符串由几个字符串块连接组成chunk1-chunk2-chunk3-chunk4,此时需要在chunk1和chunk2之间添加data1,chunk3内容修改为chunk5,chunk4的块被删除。

[1, data1, 2, chunk5, -4]

  1表示原来chunk1的内容不变,data1表示插入的新内容;-4表示删除chunk4的文件块;

let a = 1, b = 1; console.log(a, b);
// 修改为
let a = 2, b = 2; console.log(a + b);

  

基于编辑距离的增量更新机制

上面方式节约资源的量取决于块的大小和内容变化的块序号分布。根据编辑距离算法增量更新的方式可以真正做到字符级别的更新。它指的是从一个字符串变换到另一个字符串所需要的最少变化操作步骤。如果能计算获取两个文件对比变化时每个字符的操作步骤,就可以将操作步骤作为增量文件下载,然后在浏览器端进行代码的运算更新了。不过这种情况对于少量的字符更新很有用,如果一次更新的内容很多,生成的增量文件很可能比源文件还大,所以实际使用过程中需要结合具体情况,在上述两种增量方式中选择。

资源覆盖率统计

有了前端资源的离线和更新机制,就要考虑在每次新资源包发布后统计新版本的更新覆盖率。这对于增量更新尤为重要,如果发现某个版本的使用为0或接近0,该版本就无需在维护。方式有很多中,最简单的就是上报版本号,每次PV统计时带上版本号,最后根据PV中的版本号来统计访问不同版本上用户的分布情况。

时间: 2024-10-14 00:25:50

【转】基于localStorage的资源离线和更新技术的相关文章

基于Quick-cocos2d-x的资源更新方案

昨天写了一篇关于更新方案的理论 游戏开发:通过路径搜索优先级来进行补丁升级(从端游到手游) 今天继续细化一下 由于新项目采用的是Quick-cocos2d-x,那我就直接给出我基于Quick-cocos2d-x-master( > 2.2.3 rc) 的更新方案吧 此更新方案要解决以下几个问题 一.资源.代码在线更新 二.framework.update模块自更新 三.玩家安装新版本后,减少不必要的更新 四.更新中断的处理 五.Quick-cocos2d-x中,遇上的问题 做到上面几点后,我觉得

转转hybrid app web静态资源离线系统实践

一.前言 目前的转转app是一个典型的hybrid app,采用的是业内主流的做法: 客户端内有大量业务页面使用webview内加载h5页面承载. 其优点是显而易见的,即:web页面上线频度满足快速迭代的业务需求,不受客户端审核和发版的时间限制,也可以将各个业务线的开发工作分摊到各个业务的fe团队上,使得个业务线可以并行开发. 而缺点,则不言而喻的在于客户端内webview加载h5页面,准确来说是web应用的性能和体验,是肯定不及客户端的.本篇文章中,笔者将会梳理立足于本团队内,根据团队的特点和

为什么我执行了发布操作,但是线上的资源并没有更新?

随着整个互联网时代的发展,前后端职能的分离,在过去的一段时间里,前后端各自仅只关注自己最擅长的领域.但是,随着"大前端"时代的到来,前端们又一次开始需要关注后端,或者前后端链接的问题了. 本文起源于笔者的一次线上发布经历,事情的前因后果大概就如何题目所提到的,但是诡异的还不仅如此,当笔者执行了release操作之后,如果用之前访问的链接(如http://www.examplae.com)去访问执行了发布的web应用的话,会发现资源并没有更新,但是如果给这个链接加上一个参数(如http:

【性能优化】懒、懒加载、懒动画 --- 基于window滚动事件来实时更新DOM的视图状态,以表明是否在规定的可视区,并作有change回调

/* * * 扩展jq原型: 懒.懒加载.懒动画 * --- 基于window滚动事件来实时更新DOM的视图状态,以表明是否在规定的可视区,并作有change回调 * * $jq.viewChange( {top:100,bottom:100,change:function(status){}} ) --- status: 'in'/'out' * $jq.viewChange('off') * * $jq[n].viewChange.status = 'in'/'out' ----- 状态为'

Spring基于ThreadLocal的“资源-事务”线程绑定设计的缘起

题目起的有些拗口了,简单说,这篇文章想要解释Spring为什么会选择使用ThreadLocal将资源和事务绑定到线程上,这背后有着什么样的起因和设计动机,通过分析帮助大家更清晰地认识Spring的线程绑定机制.本文原文链接:http://blog.csdn.net/bluishglc/article/details/7784502 转载请注明出处! “原始”的数据访问写法 访问任何带有事务特性的资源系统,像数据库,都有着相同的特点:首先你需要获得一个访问资源的“管道”,对于数据库来说,这个所谓的

基于server broker 的数据实时更新

Service Broker介绍:SQL Server Service Broker 为消息和队列应用程序提供 SQL Server 数据库引擎本机支持.这使开发人员可以轻松地创建使用数据库引擎组件在完全不同的数据库之间进行通信的复杂应用程序.开发人员可以使用 Service Broker 轻松生成可靠的分布式应用程序.使用 Service Broker 的应用程序开发人员无需编写复杂的内部通信和消息,即可跨多个数据库分发数据工作负荷.因为 Service Broker 会处理会话上下文中的通信

Android SDK离线安装更新方法

直接使用Android SDK Manager进行下载.更新速度很慢,有时候会出现错误.网上查找了不少网友的方法,做个总结. 1.启动Android SDK Manager,并等待reposity加载完成. 2.点击右下角图标,显示Android SDK Manager Log,内容如下: Fetching http://dl-ssl.google.com/android/repository/addons_list-2.xml Fetched Add-ons List successfully

linux学习资源(不断更新中)

1.http://www.kernel.org,linux内核(源码)下载 2.http://www.oldlinux.org/index_cn.html,<Linux内核0.11(0.95)完全注释> 3.书籍列表: 101-深入理解Linux内核(第三版 英文版)-1030页.pdf  102-深入分析Linux_内核源代码--550页.pdf  103-Linux下的C编程-438页.pdf  104-linux从入门到精通-372页.pdf  105-Linux菜鸟专用资料-595页.

基于libUSB的USB设备固件更新程序(下载数据)(转)

源:基于libUSB的USB设备固件更新程序(下载数据) 本文紧接上一篇日志:基于libUSB-Win32的USB设备固件更新程序(前言),相关背景以及起因等,此处不再赘述,如感兴趣请移步. libUSB-Win32给出的example里面,有一个bulk.c文件,分析其关键代码,结合libusb官方文档,摘出其关键代码如下: int main(void) { usb_dev_handle *dev = NULL; /* the device handle */ usb_init(); /* i