1、应用场景
离线访问对基于网络的应用而言越来越重要。虽然所有浏览器都有缓存机制,但它们并不可靠,也不一定总能起到预期的作用。HTML5 使用ApplicationCache 接口解决了由离线带来的部分难题。前提是你需要访问的web页面至少被在线访问过一次。
2、使用缓存接口可为您的应用带来以下三个优势:
离线浏览 – 用户可在离线时浏览您的完整网站
速度 – 缓存资源为本地资源,因此加载速度较快。
服务器负载更少 – 浏览器只会从发生了更改的服务器下载资源。
3、离线本地存储和传统的浏览器缓存有什么不同呢?
离线存储为整个web提供服务,浏览器缓存只缓存单个页面;
离线存储可以指定需要缓存的文件和哪些文件只能在线浏览,浏览器缓存无法指定;
离线存储可以动态通知用户进行更新。
4、如何实现
离线存储是通过manifest文件来管理的,需要服务器端的支持,不同的服务器开启支持的方式也是不同的。对于Tomcat需要修改 /conf/web.xml文件,添加如下MIMEType配置:
- <mime-mapping>
- <extension>manifest</extension>
- <mime-type>text/cache-manifest</mime-type>
- </mime-mapping>
注意,<extension>manifest</extension>中内容必须和manifest文件后缀名一致。
一个典型的manifest文件应该类似这样:
- CACHE MANIFEST//必须以这个开头
- version 1.0 //最好定义版本,更新的时候只需修改版本号
- CACHE:
- m.png
- test.js
- test.css
- NETWORK:
- *
- FALLBACK
- online.html offline.html
其中CACHE指定需要缓存的文件;NETWORK指定只有通过联网才能浏览的文件,*代表除了在CACHE中的文件;FALLBACK每行分别指定在线和离线时使用的文件
要让manifest管理存储。
有了manifest文件后,还需要在html标签中定义manifest属性,如下:
- <!DOCTYPE html>
- <html lang="en" manifest='test.manifest'>
- <head>
- <meta charset="UTF-8">
- <title></title>
- </head>
- <body>
- </body>
- </html>
5、通过JS动态控制更新
应用在离线后将保持缓存状态,除非发生以下某种情况:
用户清除了浏览器对您网站的数据存储。
清单文件经过修改。请注意:更新清单中列出的某个文件并不意味着浏览器会重新缓存该资源。清单文件本身必须进行更改。
缓存状态:
window.applicationCache 对象是对浏览器的应用缓存的编程访问方式。其 status 属性可用于查看缓存的当前状态:
- var appCache = window.applicationCache;
- switch (appCache.status) {
- case appCache.UNCACHED: // UNCACHED == 0
- return 'UNCACHED';
- break;
- case appCache.IDLE: // IDLE == 1
- return 'IDLE';
- break;
- case appCache.CHECKING: // CHECKING == 2
- return 'CHECKING';
- break;
- case appCache.DOWNLOADING: // DOWNLOADING == 3
- return 'DOWNLOADING';
- break;
- case appCache.UPDATEREADY: // UPDATEREADY == 4
- return 'UPDATEREADY';
- break;
- case appCache.OBSOLETE: // OBSOLETE == 5
- return 'OBSOLETE';
- break;
- default:
- return 'UKNOWN CACHE STATUS';
- break;
- };
要以编程方式更新缓存,请先调用 applicationCache.update()。此操作将尝试更新用户的缓存(前提是已更改清单文件)。最后,当applicationCache.status 处于 UPDATEREADY 状态时,调用 applicationCache.swapCache() 即可将原缓存换成新缓存。
- var appCache = window.applicationCache;
- appCache.update(); // Attempt to update the user's cache.
- ...
- if (appCache.status == window.applicationCache.UPDATEREADY) {
- appCache.swapCache(); // The fetch was successful, swap in the new cache.
- }
请注意:以这种方式使用 update() 和 swapCache() 不会向用户提供更新的资源。此流程只是让浏览器检查是否有新的清单、下载指定的更新内容以及重新填充应用缓存。因此,还需要对网页进行两次重新加载才能向用户提供新的内容,其中第一次是获得新的应用缓存,第二次是刷新网页内容。
好消息是,您可以避免重新加载两次的麻烦。要使用户更新到最新版网站,可设置监听器,以监听网页加载时的 updateready 事件:
- //Check if a new cache is available on page load.
- window.addEventListener('load', function(e) {
- window.applicationCache.addEventListener('updateready', function(e) {
- if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {
- // Browser downloaded a new app cache.
- // Swap it in and reload the page to get the new hotness.
- window.applicationCache.swapCache();
- if (confirm('A new version of this site is available. Load it?')) {
- window.location.reload();
- }
- } else {
- // Manifest didn't changed. Nothing new to server.
- }
- }, false);
- }, false);
6、APPCACHE 事件(详见W3C Spec:http://www.w3.org/TR/2012/WD-html5-20120329/offline.html#offline)
Event name | Interface | Fired when... | Next events |
---|---|---|---|
checking |
Event |
The user agent is checking for an update, or attempting to download the manifest for the first time. This is always the first event in the sequence. | noupdate , downloading ,obsolete , error |
noupdate |
Event |
The manifest hadn't changed. | Last event in sequence. |
downloading |
Event |
The user agent has found an update and is fetching it, or is downloading the resources listed by the manifest for the first time. | progress , error , cached ,updateready |
progress |
ProgressEvent |
The user agent is downloading resources listed by the manifest. | progress , error , cached ,updateready |
cached |
Event |
The resources listed in the manifest have been downloaded, and the application is now cached. | Last event in sequence. |
updateready |
Event |
The resources listed in the manifest have been newly redownloaded, and the script can use swapCache() to switch to the new cache. |
Last event in sequence. |
obsolete |
Event |
The manifest was found to have become a 404 or 410 page, so the application cache is being deleted. | Last event in sequence. |
error |
Event |
The manifest was a 404 or 410 page, so the attempt to cache the application has been aborted. | Last event in sequence. |
The manifest hadn't changed, but the page referencing the manifest failed to download properly. | |||
A fatal error occurred while fetching the resources listed in the manifest. | |||
The manifest changed while the update was being run. | The user agent will try fetching the files again momentarily. |
通过对这些事件的监听处理能更好的控制应用程序文件的缓存、更新。
7.一个简单的离线缓存的应用
建一个web工程AppCache,包括四个文件:
appcache_offline.html
- <html manifest="clock.manifest">
- <head>
- <title>AppCache Test</title>
- <link rel="stylesheet" href="clock.css">
- <script src="clock.js"></script>
- </head>
- <body>
- <p><output id="clock"></output></p>
- <div id="log"></div>
- </body>
- </html>
clock.manifest
- CACHE MANIFEST
- #VERSION 1.0
- CACHE:
- clock.css
- clock.js
clock.css
- output { font: 2em sans-serif; }
- clock.js
- setTimeout(function () {
- document.getElementById('clock').value = new Date();
- }, 1000);
联网情况下访问:http://localhost:8080/AppCache/appcache_offline.html,页面间断显示系统当前时间;断开网络后仍然可以正常访问。如下所示:
Wed Oct 17 2012 18:34:41 GMT+0800 (CST)