HTML5 Application Cache

1、应用场景

离线访问对基于网络的应用而言越来越重要。虽然所有浏览器都有缓存机制,但它们并不可靠,也不一定总能起到预期的作用。HTML5 使用ApplicationCache 接口解决了由离线带来的部分难题。前提是你需要访问的web页面至少被在线访问过一次。

2、使用缓存接口可为您的应用带来以下三个优势:
离线浏览 – 用户可在离线时浏览您的完整网站
速度 – 缓存资源为本地资源,因此加载速度较快。
服务器负载更少 – 浏览器只会从发生了更改的服务器下载资源。
3、离线本地存储和传统的浏览器缓存有什么不同呢?
离线存储为整个web提供服务,浏览器缓存只缓存单个页面;
离线存储可以指定需要缓存的文件和哪些文件只能在线浏览,浏览器缓存无法指定;
离线存储可以动态通知用户进行更新。
4、如何实现

离线存储是通过manifest文件来管理的,需要服务器端的支持,不同的服务器开启支持的方式也是不同的。对于Tomcat需要修改 /conf/web.xml文件,添加如下MIMEType配置:

  1. <mime-mapping>
  2.        <extension>manifest</extension>
  3.        <mime-type>text/cache-manifest</mime-type>
  4. </mime-mapping>

注意,<extension>manifest</extension>中内容必须和manifest文件后缀名一致。

 

一个典型的manifest文件应该类似这样:

 

  1. CACHE MANIFEST//必须以这个开头
  2. version 1.0 //最好定义版本,更新的时候只需修改版本号
  3. CACHE:
  4.     m.png
  5.     test.js
  6.     test.css
  7. NETWORK:
  8.     *
  9. FALLBACK
  10.     online.html offline.html

其中CACHE指定需要缓存的文件;NETWORK指定只有通过联网才能浏览的文件,*代表除了在CACHE中的文件;FALLBACK每行分别指定在线和离线时使用的文件
要让manifest管理存储。

有了manifest文件后,还需要在html标签中定义manifest属性,如下:

  1. <!DOCTYPE html>
  2. <html lang="en" manifest='test.manifest'>
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title></title>
  6. </head>
  7. <body>
  8. </body>
  9. </html>

5、通过JS动态控制更新
应用在离线后将保持缓存状态,除非发生以下某种情况:
用户清除了浏览器对您网站的数据存储。
清单文件经过修改。请注意:更新清单中列出的某个文件并不意味着浏览器会重新缓存该资源。清单文件本身必须进行更改。

缓存状态:
window.applicationCache 对象是对浏览器的应用缓存的编程访问方式。其 status 属性可用于查看缓存的当前状态:

  1. var appCache = window.applicationCache;
  2. switch (appCache.status) {
  3.   case appCache.UNCACHED: // UNCACHED == 0
  4.     return 'UNCACHED';
  5.     break;
  6.   case appCache.IDLE: // IDLE == 1
  7.     return 'IDLE';
  8.     break;
  9.   case appCache.CHECKING: // CHECKING == 2
  10.     return 'CHECKING';
  11.     break;
  12.   case appCache.DOWNLOADING: // DOWNLOADING == 3
  13.     return 'DOWNLOADING';
  14.     break;
  15.   case appCache.UPDATEREADY:  // UPDATEREADY == 4
  16.     return 'UPDATEREADY';
  17.     break;
  18.   case appCache.OBSOLETE: // OBSOLETE == 5
  19.     return 'OBSOLETE';
  20.     break;
  21.   default:
  22.     return 'UKNOWN CACHE STATUS';
  23.     break;
  24. };

要以编程方式更新缓存,请先调用 applicationCache.update()。此操作将尝试更新用户的缓存(前提是已更改清单文件)。最后,当applicationCache.status 处于 UPDATEREADY 状态时,调用 applicationCache.swapCache() 即可将原缓存换成新缓存。

 

  1. var appCache = window.applicationCache;
  2. appCache.update(); // Attempt to update the user's cache.
  3. ...
  4. if (appCache.status == window.applicationCache.UPDATEREADY) {
  5.   appCache.swapCache();  // The fetch was successful, swap in the new cache.
  6. }

 

请注意:以这种方式使用 update() 和 swapCache() 不会向用户提供更新的资源。此流程只是让浏览器检查是否有新的清单、下载指定的更新内容以及重新填充应用缓存。因此,还需要对网页进行两次重新加载才能向用户提供新的内容,其中第一次是获得新的应用缓存,第二次是刷新网页内容。

好消息是,您可以避免重新加载两次的麻烦。要使用户更新到最新版网站,可设置监听器,以监听网页加载时的 updateready 事件:

  1. //Check if a new cache is available on page load.
  2. window.addEventListener('load', function(e) {
  3.   window.applicationCache.addEventListener('updateready', function(e) {
  4.     if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {
  5.       // Browser downloaded a new app cache.
  6.       // Swap it in and reload the page to get the new hotness.
  7.       window.applicationCache.swapCache();
  8.       if (confirm('A new version of this site is available. Load it?')) {
  9.         window.location.reload();
  10.       }
  11.     } else {
  12.       // Manifest didn't changed. Nothing new to server.
  13.     }
  14.   }, false);
  15. }, 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. noupdatedownloading,obsoleteerror
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. progresserrorcached,updateready
progress ProgressEvent The user agent is downloading resources listed by the manifest. progresserrorcached,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

  1. <html manifest="clock.manifest">
  2.   <head>
  3.     <title>AppCache Test</title>
  4.     <link rel="stylesheet" href="clock.css">
  5.     <script src="clock.js"></script>
  6.   </head>
  7.   <body>
  8.     <p><output id="clock"></output></p>
  9.     <div id="log"></div>
  10.   </body>
  11. </html>

clock.manifest

  1. CACHE MANIFEST
  2. #VERSION 1.0
  3. CACHE:
  4. clock.css
  5. clock.js

clock.css

  1. output { font: 2em sans-serif; }
  1. clock.js
  2. setTimeout(function () {
  3.     document.getElementById('clock').value = new Date();
  4. }, 1000);

联网情况下访问:http://localhost:8080/AppCache/appcache_offline.html,页面间断显示系统当前时间;断开网络后仍然可以正常访问。如下所示:

 

Wed Oct 17 2012 18:34:41 GMT+0800 (CST)

HTML5 Application Cache
标签: