1、1基于 HTML5 的离线存储技术摘要:HTML5 是 W3C 的新标准,不仅提升了 Web 页面的性能,也有很多的 API 接口,开发人员使用这些接口,可以很容易地创建更丰富的Web 程序。利用 HTML5 离线存储技术,使用 DOM 存储和 Web SQL Database 存储机制可以开发离线的 Web 应用程序。 关键词:Web;HTML5;离线;DOM Storage 中图分类号:TP393.09 文献标识码:A 文章编号:1008-4738(2013)02-0103-04 0 引言 随着 HTML51技术发展迅速,在 HTML 5 平台上,视频、音频、图像、动画以及同电脑的交互都被
2、标准化。HTML 功能越来越丰富,支持图片上传拖拽、支持 Localstorage、支持 Web SQL Database、支持文件存储Api 等等。致力于将 Web 带入一个更为成熟的应用平台,本文介绍 HTML 5 的离线缓存2Web 应用的功能。 离线存储的三大核心功能作用: 离线资源缓存需要一种方式来指明应用程序离线工作时所需的资源文件。这样,浏览器才能在在线状态时,把这些文件缓存到本地。此后,当用户离线访问应用程序时,这些资源文件会自动加载,从而让用户正常使用。HTML5 中,通过 Cache manifest 文件指明需要缓存的资源,并支持自动和手动两种缓存3更新方式。 2在线状态
3、检测:开发者需要知道浏览器是否在线,这样才能够针对在线或离线的状态,做出对应的处理。在 HTML5 中,提供了两种检测当前网络是否在线的方式。 本地数据存储:离线时,需要能够把数据存储到本地,以便在线时同步到服务器上。为了满足不同的存储需求,HTML5 提供了 DOM Storage 和 Web SQL Database 两种存储机制45。前者提供了易用的 key/value 对存储方式,而后者提供了基本的关系数据库存储功能。 1 离线存储的实现 (1)在 html 标签里通过 manifest 属性引用一个 cache.manifest文件,该文件里声明了浏览器需缓存的所有资源文件,如下所示
4、: 离线缓存示例页面 var _gaq = _gaq | ;_gaq.push(_setAccount, UA-22575914-1);_gaq.push(_setDomainName, );_gaq.push(_trackPageview);(function () var ga = document.createElement(script); ga.type = text/javascript; ga.async = true;ga.src = (https: = 3document.location.protocol ? https:/ssl : http:/www) + .googl
5、e- s = document.getElementsByTagName(script)0; s.parentNode.insertBefore(ga, s);)();var _userid = ;var _siteid =75;var _istoken = 1;var _model = Model03; WebPageSpeed =234; UrchinTrack(); (2)关于 cache.manifest 的定义 CACHE MANIFEST # 注释:需要缓存的文件,无论在线与否,均从缓存里读取 chched.js cached.css # 注释:不缓存的文件,无论缓存中存在与否,均
6、重新获取 NETWORK: uncached.js uncached.css # 注释:获取不到资源时的备选路径,如 index.html 访问失败,则返回 404 页面 FALLBACK: index.html 404.html 几个需要关注的细节 4cache.manifest 文件的 MIME 类型是 text/cache-manifest,至于如何让 web 服务器返回.manifest 文件时添加 Content-Type: text/cache-manifest,不同服务器配置细节不同,此处不展开。 cache.manifest 写法以 CACHE MANIFEST 开头,文件编码
7、格式必须是utf-8。 引用 cache.manifest 的 html 文档会被默认包含进缓存清单。 归纳起来,步骤如下: 配置服务器支持 cache.manifest 的 Content-type: manifest 编写 cache.manifest 文件 html 页面引用 cache.manifest 文件 2ApplicationCache 对象,及属性、事件、接口 浏览器通过 window.applicationCache 对象来及其相应属性、接口、事件供用户构建离线应用,详细可见 applicationCache /当前文档对应的 applicationCache 对象 win
8、dow.applicationCache /当前缓存所处的状态,为 05 的整数值,分别对应一个状态,并分别对应一个常量 window.applicationCache.status window.applicationCache.UNCACHED = 0/未缓存,比如一个页面没有制定缓存清单,其状态就是 UNCACHED window.applicationCache.IDLE = 1 /空闲,缓存清单指定的文件已经全部被页面缓存,此时状态就是 IDLE 5window.applicationCache.CHECKING = 2 /页面正在检查当前离线缓存是否需要更新 window.appl
9、icationCache.DOWNLOADING = 3 /页面正在下载需要更新的缓存文件 window.applicationCache.UPDATEREADY = 4 /页面缓存更新完毕 window.applicationCache.OBSOLETE = 5 /缓存过期,比如页面检查缓存是否过期时,发现服务器上的.manifest 文件被删掉了 /常用 API,在后面会稍详细介绍 window.applicationCache.update() /update 方法调用时,页面会主动与服务器通信,检查页面当前的缓存是否为最新的,如不是,则下载更新后的资源 window.applicati
10、onCache.swapCache() /updateready 后,更新到最新的应用缓存 除了上面提及的属性、接口外,window.applicationCache 还包含了一系列的事件,大部分与上面提到的 window.applicationCache.status对应,如下表: 事件名关联属性事件释义 oncheckingCHECKING见上文对关联属性的解释 ondownloadingDOWNLOADING onupdatereadyUPDATEREADY onobsoleteOBSOLETE oncachedIDLE 6onerror更新出错,如检查更新时.manifest 被人误删
11、了 onnoupdate检查后,发现缓存无需更新 onprogress- 3 访问缓存应用,相应触发事件,及其对应状态 假设我们第一次在 chrome 里面访http:/localhost/html5/has_cache/cache.html,如下所示: 打开控制台,看到如下: JZXC;%50%50 由上到下依次为(cache = window.applicationCache):检查是否需要下载/更新缓存,cache.status=cache.CHECKING 发现本地还没有缓存文件,开始下载,cache.status=cache.DOWNLOADING 正在下载缓存文件,cache.st
12、aus=cache.PROGRESS,下载完毕,并缓存在本地,cache.status=cache.CACHED。 再次访问http:/localhost/blog/html5/cache/has_cache/cache.html 假设.manifest 没有变化,打开控制台,如下所示: JZXC;%50%50 由上到下依次为: 1)检查是否需要下载/更新缓存,cache.status=cache.CHECKING发现服务器上没有更新,cache.status=cahce.NOUPDATE。 2)假设 cache.manifest 已经发生变化,则如下截图所示: 7JZXC;%50%50 4
13、如何更新离线缓存 (1)本地手动删除,各浏览器实现方式不同。以 chrome 为例,输入 chrome:/appcache-internals/,可以查看本地的离线缓存,也可以进行删除。 (2)更新.manifest 文件,浏览器检测到.manifest 变更后,会主动更新本地缓存。 (需要注意的是,假如没有更新.manifest,即使你对缓存清单里的文件进行了修改,浏览器依旧会顽强地从本地缓存里面读取修改之前的文件) 。 (3)通过 applicationCache 对象的 API 来主动更新,主要涉及接口为 update()以及 swapCache() 。 cache.update() ,
14、说明:启动应用缓存下载进程,由于浏览器通常会主动检查.manifest 文件确认缓存是否需要更新,所以大部分情况下这个方法是没必要的。但对于一些可能在浏览器里待上长达一个星期左右的应用,比如电子邮箱,这个方法就会派上用场,比如每隔 1 天检查下本地缓存的一些文件在服务器上是否已经更新。 cache.swapCache() ,说明:如果浏览器已经更新了新的离线缓存,则切到最新的缓存去。对于已经加载解析的资源,如 CSS、图片等,并不会导致其重新加载、解析一遍。唯一的变化就是,后续对缓存资源的请求,获取到的都是本地的最新缓存。需要注意的是,swapCache 方法需要在 updateready 事
15、件触发后调用。调用 update 方法,更新了本地缓存,但如果不调用 swapCache 方法,在本次会话中,重新请求已经更新过的8资源,还是拿到老的文件。 5 演示:update 后是否调用 swapCache 的区别 假设有 cache.html、cache.manifest、cache.js,分别如下: cache.html 离线缓存 var _gaq = _gaq | ;_gaq.push(_setAccount, UA-22575914-1);_gaq.push(_setDomainName, );_gaq.push(_trackPageview);(function () var
16、ga = document.createElement(script); ga.type = text/javascript; ga.async = true;ga.src = (https: = document.location.protocol ? https:/ssl : http:/www) + .google- s = document.getElementsByTagName(script)0; s.parentNode.insertBefore(ga, s);)();var _userid = ;var _siteid =75;var _istoken = 1;var _mod
17、el = Model03; WebPageSpeed =172; UrchinTrack(); var cache = window.applicationCache; conso.log(test: + test) ; /cache.js 定义的一个变量,初始值为 10 function load(url, callback) 9var script = document.createElement(script) ; script.src = url; script.onload = function()callback & callback() ; document.body.appen
18、dChild(script) ; setTimeout(function() cache.addEventListener(updateready, function()log(更新完毕) ; /cache.swapCache() ; load(cache.js, function()log(test: + test) ;/test: 10 ) ; ) ; cache.update() ; , 20*1000) ; cache.js var test = 10; /测试用变量 cache.manifest CACHE MANIFEST # Javascript v0 ./cache.js 假设
19、我们现在已经打开浏览器访问http:/localhost/html5/cache/mod_cache/cache.html,在打开页面5s 左右后,有人修改了 cache.js 里变量改 test 的值,如下:var test 10= 11; /最初为 10,现在修改为 11,同时修改了 cache.manifest 文件(随便在注释里添加几个数字即可) 。之前已经设置了 20s 后,调用update 方法检查缓存资源是否更新,此时浏览器发现 cache.manifest 文件发生变化,且 cache.js 的确被修改的,于是更新了本地缓存。 CACHE MANIFEST # Javascri
20、pt v11111 ./cache.js 在 cache.html 里面,将 cache.swapCache()这句注释掉了,是否将这句注释掉,是否有差别?差别在哪里?直接看结果: (1)无 cache.swapCache() ,输出结果:test: 10 (2)有 cache.swapCache() ,输出结果:test: 11 结合 API 说明不难想到两者之间的差别,当没有调用cache.swapCache()时候,即使重新请求 cache.js,加载的还是缓存更新前的 cache.js(老的缓存) ;若调用了 cache.swapCache() ,则重新请求 cache.js 时,加载的是已经更新后的 cache.js(最新的缓存) 。 6 总结 传统的 Web 技术开发的应用最致命的就是用户体验问题,页面跳转和过多的请求,大大影响了加载速度和用户体验。如果采用 HTML5 的离线储存访问 Web 应用,对于用户来说非常重要,用户可以访问本地的缓存文件,仅加载被修改过的离线资源,避免同一资源对服务器多次的请求,并且降低了对服务器的访问压力,提升了 Web 访问速度。 参考文献