为了能够让用户在离线状态下继续访问 Web 应用,需要一种方式来指明应用程序离线工作时所需的资源文件。这样,浏览器才能在在线状态时,把这些文件缓存到本地。此后,当用户离线访问应用程序时,这些资源文件会自动加载,从而让用户正常使用。HTML5 中,通过 cache manifest 文件指明需要缓存的资源,并支持自动和手动两种缓存更新方式。
开发者需要提供一个 cache manifest 文件。这个文件中列出了所有需要在离线状态下使用的资源,浏览器会把这些资源缓存到本地。
我们通过 W3C 提供的示例来说明。Clock Web 应用由三个文件“clock.html”、“clock.css”和“clock.js”组成。
<!-- clock.html -->
< !DOCTYPE HTML>
<html>
<head>
<title>Clock</title>
<script src="clock.js"></script>
<link rel="stylesheet" href="clock.css">
</link></head>
<body>
<p>The time is: <output id="clock"></output></p>
</body>
</html>
/* clock.css */
output { font: 2em sans-serif; }
/* clock.js */
setTimeout(function () {
document.getElementById('clock').value = new Date();
}, 1000);
当用户在离线状态下访问“clock.html”时,页面将无法展现。为了支持离线访问,开发者必须添加 cache manifest 文件,指明需要缓存的资源。这个例子中的 cache manifest 文件为“clock.manifest”,它声明了 3 个需要缓存的资源文件“clock.html”、“clock.css”和“clock.js”。 clock.manifest 代码
CACHE MANIFEST
clock.html
clock.css
clock.js
添加了 cache manifest 文件后,还需要修改“clock.html”,把 标签的 manifest 属性设置为“clock.manifest”。修改后的“clock.html”代码如下。
<!-- clock.html -->
< !DOCTYPE HTML>
<html manifest="clock.manifest">
<head>
<title>Clock</title>
<script src="clock.js"></script>
<link rel="stylesheet" href="clock.css">
</link></head>
<body>
<p>The time is: <output id="clock"></output></p>
</body>
</html>
修改后,当用户在线访问“clock.html”时,浏览器会缓存“clock.html”、“clock.css”和“clock.js”文件;而当用户离线访问时,这个 Web 应用也可以正常使用了。
注意:
manifest文件的MIME-type必须是text/cache-manifest (需要服务器端设置)
在测试中发现,各浏览器更新缓存的机制各异:chrome修改manifest就可以更新缓存了,但却无法加载manifest之外的资源;而firefox需要手动删除本地缓存数据。 种种的这些兼容性问题,可以给NETWORK添加上通配符*来修正:
NETWORK:*
具体的原因可能是在启用离线应用后浏览器不会加载manifest设定之外的资源;而且firefox等也把manifest文件给缓存了,导致无法获取最新的manifest资源列表。
下面说明书写 cache manifest 文件需要遵循的格式。
首行必须是 CACHE MANIFEST。
其后,每一行列出一个需要缓存的资源文件名。
需要注意的是一行一个文件,也可以使用绝对路径或者URLs。
可根据需要列出在线访问的白名单。白名单中的所有资源不会被缓存,在使用时将直接在线访问。声明白名单使用 NETWORK:标识符。
如果在白名单后还要补充需要缓存的资源,可以使用 CACHE:标识符。
如果要声明某 URI 不能访问时的替补 URI,可以使用 FALLBACK:标识符。其后的每一行包含两个 URI,当第一个 URI 不可访问时,浏览器将尝试使用第二个 URI。
注释要另起一行,以 # 号开头。
cache manifest 中各类标识符的使用示例。
CACHE MANIFEST
# 上一行是必须书写的。
images/sound-icon.png
images/background.png
NETWORK:
comm.cgi
# 下面是另一些需要缓存的资源,在这个示例中只有一个 css 文件。
CACHE:
style/default.css
FALLBACK:
/files/projects /projects
应用程序可以等待浏览器自动更新缓存,也可以使用 Javascript 接口手动触发更新。
1.自动更新
浏览器除了在第一次访问 Web 应用时缓存资源外,只会在 cache manifest 文件本身发生变化时更新缓存。而 cache manifest 中的资源文件发生变化并不会触发更新 。 2.手动更新
开发者也可以使用 window.applicationCache 的接口更新缓存。方法是检测 window.applicationCache.status 的值,如果是 UPDATEREADY,那么可以调用 window.applicationCache.update() 更新缓存。
现在来了解下离线应用的API:
/*当前文档的ApplicationCache对象*/
var cache = window.applicationCache;
/*
*当前worker的ApplicationCache对象*worker在本文第五节介绍
*/
var cache = self.applicationCache;
/*
*属性,返回当前离线应用的状态
* UNCACHED (数值0):未启用离线应用
* IDLE (数值1):已开启离线应用,但本地缓存的资源是最新的,并且未标记为废弃资源
* CHECKING (数值2):当前更新缓存的状态为“检查中”
* DOWNLOADING (数值3):当前更新缓存的状态为“下载资源中”
* UPDATEREADY (数值4):当前更新缓存的状态为“更新完毕”
* OBSOLETE (数值5):已开启离线应用,但缓存资源都已标记为废弃
*/
cache.status
/*
*方法,下载资源到本地
*如果没有cache需要更新,则抛出 INVALID_STATE_ERR 异常
*/
cache.update();
/*
*方法,更新缓存到最新的资源
*如果没有新的资源,则抛出INVALID_STATE_ERR异常
*并不会使本次加载的页面立即重新加载资源,仅有在执行该方法后刷新页面才能看到最新的资源。
*/
cache.swapCache();
事件处理器:
checkingEvent 检查是否需要更新,或者在第一次下载manifest文件时。 最先执行的事件。
noupdateEvent manifest 文件未修改,不需要更新。Last event in sequence.
downloadingEvent 需要更新缓存,或者第一次下载资源时。
progressProgressEvent 下载资源中。
cachedEvent 资源已下载完成,并且已完成缓存最后的事件。
updatereadyEvent 资源更新完毕,并且可以用swapCache()来启用新的缓存。最后的事件。
obsoleteEvent 加载manifest文件时遇到401或404错误,所以缓存将被删除。最后的事件。
errorEvent 加载manifest文件时遇到401或404错误,将中断缓存网页。最后的事件。
支持浏览器:Firefox 3.0, Safari 4.0, Chrome 5.0, Opera 10.6