html5离线存储入门基础

所有的浏览器都有自己的缓存机制,但那些机制并不可靠而且难以控制,在你做web开发的时候可能经常因为浏览器缓存带来的问题而烦恼不已。html5通过ApplicationCache接口解决了一些问题,并且使离线存储成为可能,离线存储使得你的web应用可以在用户离线的状况下进行访问。

这个技术显然至少有三个好处:

  • 最直接的好处就是用户可以离线访问你的web应用
  • 因为文件被缓存在本地使得web页面加载速度提升许多
  • 离线应用只加载被修改过的资源,因此大大降低了用户请求对服务器造成的负载压力

如何实现离线文件存储?

你的服务器得先支持html5!是的,这句话看上去像是以前在css森林群里大家说的“我的服务器不支持div+css”一样的玩笑话。但我很严肃的告诉你,要实现离线存储的应用,你确实需要服务器的支持!容我细细道来,先来看看html5的离线文件存储应用对你的代码有什么要求,你需要在页面的html标签中通过manifest属性引用一个manifest文件来使得你的应用可缓存。简单地说,manifest文件是一个文本文件,它罗列了离线访问应用时所需缓存的文件清单(注意:引用该manifest文件的页面,不管你有没有罗列到清单中,都会被缓存),但不只是这样。代码像下面这样:

<html manifest="test.manifest">  
  ...  
</html>  

当然,这个manifest的文件路径用绝对路径和相对路径都可以,甚至可以引用其他服务器上的manifest文件。该文件所对应的mime-type应该是text/cache-manifest的,所以你需要配置服务器来发送对应的MIME类型信息,服务器配置不在讨论范围内,请自行去了解吧。接下来要看的是manifest文件的结构,它的结构很简单,我们来看下面的例子:

MANIFEST

CACHE MANIFEST

index.html

style.css

images/logo.png

scripts/mootools.js

这是最简单的一个manifest文件的样子,正如前面所提到的,文件罗列了需要被缓存的文件清单,第一行中的CACHE MANIFEST 是必须的,每个站点有5MB的空间来存储这些数据,如果manifest文件或文件里所列的文件无法加载,整个缓存更新过程将无法进行,浏览器会使用最后一次成功的缓存。前面说过manifest文件不只是罗列要缓存的文件,那么它还有其他什么作用呢?让我们来看个稍微复杂点的例子:

MANIFEST

CACHE MANIFEST

# wanz app v1

# 指明缓存入口

CACHE:

index.html

style.css

images/logo.png

scripts/main.js

# 以下资源必须在线访问

NETWORK:

login.php

# 如果index.php无法访问则用404.html代替

FALLBACK:

/index.php /404.html

有经验的同学一定可以看出来#是用来注释一行的,但它还有一个小作用。web应用的缓存只有在manifest文件被修改的情况下才会被更新,所以如果你只是修改了被缓存的文件,那么用户本地的缓存还是不会被更新的,但是你可以通过修改manifest文件来告诉浏览器需要更新缓存了。利用这点,你可以像上面的例子中那样,写一句这样的注释一个文件版本:

# wanz app v1

这样写有三个好处:

  • 你可以很明确的了解离线web应用的版本
  • 通过简单的修改这个版本号就可以轻易的通知浏览器更新
  • 你可以配合JavaScript程序来完成缓存更新

正如你看到的,manifest文件有三个节点,它们各自的含义如下:

CACHE:

这个是manifest文件的默认入口,在此入口之后罗列的文件 (或直接写在CACHE MANIFEST后的文件)在它们下载到本地后会被缓存起来

NETWORK:

可选的,在此节后面所罗列的文件是需要访问网络的,即使用户离线访问了也会直接跳过缓存而访问服务器

FALLBACK:

可选的,用来指定资源无法访问时的回调页面。每一行包括两个URI,第一个是资源文件URI,第二个是回调页面URI。

备注:以上描述的这些节是没有先后顺序的,而且在同一个manifest中可以多次出现

到目前为止,你应该了解如何来实现离线文件的存储了,只需要三个步骤:1,配置服务器manifest文件的MIME类型;2,编写manifest文件;3,在页面的html标签的manifest属性中引用写好的manifest文件。

如何更新离线存储?

你做到了,即使拔掉网线你也可以访问你制作的页面。于是你开始兴致勃勃的丰富你的页面,修改JavaScript代码和css来实现更炫的页面效果,然后将它们上传到服务器,结果你会发现:即使你刷新页面刷到爆,清除n次历史访问记录都无法看到你要的新的页面效果。那是因为你根本还没有更新html5的离线存储文件。现在的问题是如何更新html5离线缓存?下面的三种情况可以做到:

用户清除了离线存储的数据,这个不一定就是清理浏览器历史记录就可以做到的,因为不同浏览器管理离线存储的方式不同。比如Firefox的离线存储数据要到“选项”=>“高级”=>“网络”=>“脱机存储”里才可以清除。

manifest文件被修改,上面说的,你修改了manifest文件里所罗列的文件也不会更新缓存,而是要替换manifest文件

使用JavaScript api编写更新程序

前面两种方式很简单,自己折腾吧。我们来看第三种,首先你需要对相关的api有所了解,详细的前往查看:http://www.whatwg.org/specs/web-apps/current-work/#applicationcache

先简单介绍下ApplicationCache和它的几个重点属性及方法:

JavaScript Code复制内容到剪贴板

cache = window . applicationCache

//返回应用于当前window对象文档的ApplicationCache对象

cache = self . applicationCache

//返回应用于当前shared worker的ApplicationCache对象 [shared worker]

cache . status

//返回当前应用的缓存状态,status有五种无符号短整型值的状态:

UNCACHED = 0;

IDLE = 1;

CHECKING = 2;

DOWNLOADING = 3;

UPDATEREADY = 4;

OBSOLETE = 5;

cache . update()

//调用当前应用资源下载过程

cache . swapCache()

//更新到最新的缓存,这个不会使得之前加载的资源突然被重新加载。图片不会重新加载,样式和脚本也不会重新渲染或解析,唯一的变化是在此之后发出请求页面的资源是最新的

applicationCache对象和缓存宿主的关系是一一对应,window对象的applicationCache属性会返回关联window对象的活动文档的applicationCache对象。在获取status属性时,它返回当前applicationCache的状态,它的值有以下几种状态:

C/C++ Code复制内容到剪贴板

UNCACHED (数值 0)

//此时,ApplicationCache对象的缓存宿主与应用缓存无关联

IDLE (数值 1)

//应用缓存已经是最新的,并且没有标记为obsolete

CHECKING (数值 2)

ApplicationCache

//对象的缓存宿主已经和一个应用缓存关联,并且该缓存的更新状态是checking

DOWNLOADING (数值 3)

ApplicationCache

//对象的缓存宿主已经和一个应用缓存关联,并且该缓存的更新状态是downloading

UPDATEREADY (数值 4)

ApplicationCache

//对象的缓存宿主已经和一个应用缓存关联,并且该缓存的更新状态是idle,并且没有标记为obsolete,但是缓存不是最新的

OBSOLETE

//(数值 5)

ApplicationCache

/对象的缓存宿主已经和一个应用缓存关联,并且该缓存的更新状态是obsolete

如果update方法被调用了,浏览器user agent就必须在后台调用应用缓存下载过程;如果swapCache方法被调用了,浏览器user agent会执行以下步骤:

检查ApplicationCache的缓存宿主是否与应用缓存关联

让cache成为ApplicationCache对象的缓存宿主关联的应用缓存

如果cache的应用缓存组被标记为obsolete,那么就取消cache与ApplicationCache对象的缓存宿主的关联并取消这些步骤,此时所有资源都会从网络中下载而不是从缓存中

检查在同一个缓存组中是否存在完成标志为“完成”的应用缓存,并且版本比cache更新

让完成标志为“完成”的新cache成为最新的应用缓存

取消cache与ApplicationCache对象的缓存宿主的关联并用新cache代替关联

假设你已经写好的离线文件存储的Demo页面,通过下面的代码可以来检查,当前页面缓存的状态:

JavaScript Code复制内容到剪贴板

var appCache = window.applicationCache;

switch (appCache.status) {

case appCache.UNCACHED: // UNCACHED == 0

alert( 'UNCACHED');

break;

case appCache.IDLE: // IDLE == 1

alert( 'IDLE');

break;

case appCache.CHECKING: // CHECKING == 2

alert ('CHECKING');

break;

case appCache.DOWNLOADING: // DOWNLOADING == 3

alert( 'DOWNLOADING');

break;

case appCache.UPDATEREADY: // UPDATEREADY == 5

alert ('UPDATEREADY');

break;

case appCache.OBSOLETE: // OBSOLETE == 5

alert ('OBSOLETE');

break;

default:

alert ('UKNOWN CACHE STATUS');

break;

};

一个更新的实现过程大概是这样的:首先调用applicationCache.update()使得浏览器开始尝试更新,前提是你的manifest文件是更新过的(比如前面所说的,修改了版本号);在applicationCache.status为UPDATEREADY 状态时就可以调用applicationCache.swapCache()来将旧的缓存更新为新的。

JavaScript Code复制内容到剪贴板

var appCache = window.applicationCache;

appCache.update(); // 开始更新

if (appCache.status == window.applicationCache.UPDATEREADY) {

appCache.swapCache(); // 得到最新版本缓存列表,并且成功下载资源,更新缓存到最新

}

没错,更新过程也可以很简单,但是一个好的应用少不了容错处理,就如Ajax技术一样,你需要对更新过程进行监控,处理各种异常或提示等待状态来使你的应用更强壮,用户体验更好,因此你需要了解applicationCache的更新过程所触发的事件,它们是:onchecking,onerror,onnoupdate,ondownloading,onprogress,onupdateready,oncached和onobsolete。监听事件的代码你应该也都轻车熟路了,假设你要对更新错误进行处理,你可以这样写:

JavaScript Code复制内容到剪贴板

var appCache = window.applicationCache;

// 请求manifest文件时返回404或410,下载失败

// 或manifest文件在下载过程中源文件被修改会触发error事件

appCache.addEventListener('error', handleCacheError, false);

function handleCacheError(e) {

alert('Error: Cache failed to update!');

};

不管是manifest文件还是它所罗列的资源文件下载失败,整个更新过程就终止了,浏览器会使用上一个最新的缓存。更多关于事件的内容请前往:http://www.whatwg.org/specs/web-apps/current-work/#event-handlers

经过一段时间的测试,我建议大家在chrome下做实验,因为用firefox的实现就像屎,有这个功能却很臭!,最后献上离线应用的demo一枚:丸子的友邻

以上是html5离线存储入门基础的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>