浏览器缓存机制2-应用缓存
在公司项目中,一些移动版的WEB页面恰好用到了应用缓存,故顺便写篇文章来总结下应用缓存方面的内容。
1.应用缓存简介
应用缓存(application cache)是HTML5提供的一套缓存机制,使得WEB应用可以离线运行。除了一些旧版本的IE外,现代浏览器如firefox,chrome,safari大部分都是支持HTML5标准的。使用应用缓存主要优势有:
- 离线浏览:用户可以在离线状态浏览网页内容。
- 速度更快: 因为数据存储在浏览器缓存中,浏览器只会下载服务器发生改变的资源(只有.appcache文件状态变化时才会重新下载.appcache文件指定的缓存资源),这样可以减轻服务器的负载。
2.应用缓存配置
要开启应用缓存,需要在web页面的html标记中加上manifest属性,如下是我的测试页面test.html代码:
<html manifest="test.appcache">
<head><title>appcache</title></head>
<body>test appcache<img src="/test.gif"></img></body>
</html>
其中test.appcache文件为缓存清单文件(cache manifest),缓存的资源都是在这个清单文件指定。使用了应用缓存后,加载资源的流程是这样的(摘自参考资料1):
1)当浏览器访问一个包含manifest属性的文档时,如果应用缓存不存在,则浏览器加载文档,获取该清单中需要缓存的文件列表,生成应用缓存的第一个版本。
2)后续对该文档以及清单文件中列出的缓存资源的访问会使得浏览器直接从应用缓存加载。同时,浏览器还会向window.applicationCache对象发送一个checking事件,在遵循经典缓存的前提下获取清单文件,关于HTTP经典缓存机制请参见前一篇文章。
3)如果当前缓存清单文件是副本是最新的,浏览器将向applicationCache对象发送一个noupdate事件,至此更新过程结束。因此,如果你在服务器上修改了任何缓存资源,需要同时修改清单文件,这样浏览器才知道你的修改。
4)如果缓存清单文件已经修改,则清单文件中列出的缓存资源(也包括通过applicationCache.add方法添加到缓存中的文件)会放到一个临时缓存中,对于每个加入到临时缓存的文件,浏览器会向applicationCache发送一个progress事件。如果出现任何错误,浏览器会发送一个error事件,并暂停更新。
5)一旦所以文件都获取成功,它们会被自动移送到真正的离线缓存中,并向applicationCache 对象发送一个 cached 事件。鉴于文档早已经被从缓存加载到浏览器中,所以更新后的文档不会重新渲染,直到页面重新加载(可以手动或通过程序).也就是说,如果你的缓存资源更新了,缓存清单文件也更新了,第一次加载页面的时候并不会更新文档,只有等到页面重新加载的时候才会更新。
为了方便测试,如果需要清除离线缓存,chrome可以通过设置中的清除浏览器数据或者直接访问chrome://appcache-internals/来清除,其他浏览器参照参考资料1.
3.缓存清单文件
一个典型的缓存清单文件test.appcache如下:
CACHE MANIFEST
# v1 - 2015-03-14 23:23
# This is a comment.
CACHE:
test.html
nomanifest.html
NETWORK:
*
FALLBACK:
/fallback fallback.html
缓存清单文件第一行必须是CACHE MANIFEST
,然后可以加上注释(以#开头)。此外就是三个段落标题,含义如下:
段落标题 | 说明 |
---|---|
CACHE | 显示记录,下面列表是需要切换到应用缓存的显示资源 |
NETWORK | 网络记录,需要从网络访问的白名单列表 |
FALLBACK | 后备记录,请求资源失败时使用 |
一个应用缓存至少会包含一个资源,由 URI 指定。所有资源除了上面提到的显示记录,网络记录,后备记录外,还有一个类别叫主记录。下面一一来看一下:
1)显示记录
每行都是一个合法的URI与一个要缓存的资源相关联(本段落内不允许通配符)。每行的URI前后允许出现空白字符。显示记录是显示指定的需要加入到应用缓存的资源列表,比如上面示例的test.appcache中需要显示缓存的文件为test.html,nomanifest.html。注意的是,不是所有的文档html属性都要加manifest属性,比如我这个列表里面的nomanifest.html文档就没有manifest属性,但是只要有包含manifest属性的文档被访问后,就会自动加入到应用缓存。
2)网络记录
每一行都是一个合法URI,该段落可以用通配符,比如上面的*,指示了除了应用缓存中之外的资源需要通过网络获取。如果这里不设置的话,那么没有在应用缓存中的资源就无法访问。比如我这里如果不指定NETWORK的话,则test.gif这个图片就无法访问到。
3)后备记录
每一行都是一个合法URI(与一个资源关联),当指定的资源无法访问时访问后面的关联资源。比如访问/fallback或者它的子路径比如/fallback/child路径时,如果没有对应的资源,则会访问fallback.html.
4)主记录
主记录是指html标签中包含了manifest属性的文档,比如下面的main.html。主记录即便没有在显示记录中列出,也会在访问时加入到应用缓存。如main.html作为主记录,虽然没有在CACHE列表中,但是在访问的时候,同样会被加入到应用缓存中。
#main.html
<html manifest="test.appcache">
<head><title>main</title></head>
<body>main html</body>
</html>
4.缓存状态(摘自参考资料1)
UNCACHED(未缓存):一个特殊的值,用于表明一个应用缓存对象还没有完全初始化。
IDLE(空闲):应用缓存此时未处于更新过程中。
CHECKING(检查):清单已经获取完毕并检查更新。
DOWNLOADING(下载中):下载资源并准备加入到缓存中,这是由于清单变化引起的。
UPDATEREADY(更新就绪):一个新版本的应用缓存可以使用。有一个对应的事件 updateready,当下载完毕一个更新,并且还未使用 swapCache() 方法激活更新时,该事件触发,而不会是 cached 事件。
OBSOLETE(废弃):应用缓存现在被废弃。
可以通过下面的代码来测试缓存清单更新情况:
function onUpdateReady() {
alert('found new version!');
}
window.applicationCache.addEventListener('updateready', onUpdateReady);
if(window.applicationCache.status === window.applicationCache.UPDATEREADY) {
onUpdateReady();
}
5.总结
- 显示记录中的资源会被加入应用缓存中。显示记录中的资源文档不一定要在html标签加manifest属性,只要在列表中都会加入应用缓存。
- 主记录是指html标签包含manifest属性的文档,即便没有在显示记录的列表中,也会加入应用缓存。
- 应用缓存资源更新后,缓存清单文件也一定要同步更新,不然浏览器没有办法知晓缓存资源的变化。
- NETWORK段落必须设置,否则其他资源无法访问。
- 缓存清单文件本身不要在显示记录中,也不要被服务器以任何方式缓存。比如apache可以这样设置缓存清单文件不被缓存。
ExpiresByType text/cache-manifest "access plus 0 seconds"
- 如果访问缓存文档时加了参数,比如/test.html?name=test这样,那么也会直接访问应用缓存并加入到应用缓存中。如下面是访问chrome://appcache-internals/得到的记录,可以看到各种类型的记录:
Flags URL Size (headers and data)
Fallback, http://localhost/fallback.html 295 B
Master, http://localhost/main.html 703 B
Explicit, http://localhost/nomanifest.html 305 B
Manifest, http://localhost/test.appcache 419 B
Explicit, http://localhost/test.html 732 B
Master, http://localhost/test.html?name=test 732 B
6.参考资料
使用应用缓存(参考了大部分内容并原文摘抄不少内容,向原作者表示感谢)