一、何为离线应用
离线应用,故名思议,就是这个应用及时在没有网络的情况下,也可以继续使用,不受影响。application cache和http缓存有时候很相似,http缓存也可以把浏览过的网页缓存下来,在断网情况下也可以打开。但是http缓存是会过期的,而application cache是永久的。http缓存像是一个快照,只是保存了网页的某个状态,而离线应用是实实在在的在运行。
在chorme浏览器下,可以访问:
- application cache 地址: chrome://appcache-internals/
- http cache 地址 : chrome://cache/
查看两者
二、实现一个h5离线应用
1、在服务端添加一个识别.appcache的配置
我使用的是nginx做服务,其他也是一样的,在conf文件夹下的mime.types文件中添加
text/cache-manifest appcache;
以便这个服务器识别这个后缀名的文件
image.png
二、在前端项目添加一个manifest.appcache配置清单
CACHE MANIFEST
# v1.3
CACHE:
images/zoomIn.png
images/zoomOut.png
NETWORK:
*
FALLBACK:
good1.jpg offline/imgs/good1.jpg
CACHE MANIFEST : 清单文件的第一行必须是这个,表示这是一个清单文件
CACHE: 后面跟着需要离线的文件
NETWORK: 后面跟着的文件表示是需要从网络上获取的(如果是*,代表除了要缓存的文件其他都是通过网络请求)
FALLBACK: 这个标签是可选的,后面每一行有两个文件,表示当第一个文件访问不了时,使用第二个文件。
三、在页面添加<html lang="en" manifest="manifest.appcache">
在页面的头部的html标签中添加 manifest="manifest.appcache",指向上面的清单文件。就这样,一个离线应用就完成了,当你第一次打开带有manifest属性的网页时,浏览器就会把离线文件下载下来,以后每次运行,都直接从缓存里拿这些文件。
index.html
<script>
window.addEventListener('load', function (e) {
window.applicationCache.addEventListener('updateready',function (e) {
console.log("status")
console.log(window.applicationCache.status);
if(window.applicationCache.status == window.applicationCache.UPDATEREADY){
window.applicationCache.swapCache();
if(confirm('a new version of this site is availabel. load it?')){
window.location.reload();
}
}else {
console.log("manifest didn't change");
}
},false)
},false)
</script>
四、缓存应用的测试
在chorme浏览器下,可以按F12打开调试工具,选择“网络”,设成“offline”来模拟断网:
image.png
当你勾了offline的时候,再次请求当前页面是可以正常显示,但是其他的就告诉你未链接互联网
image.png
五、缓存更新
应用缓存只在其清单文件发生更改时才会更新。例如,如果您修改了图片资源或更改了 JavaScript 函数,这些更改不会重新缓存。您必须修改清单文件本身才能让浏览器刷新缓存文件。使用生成的版本号、文件哈希值或时间戳创建注释行,可确保用户获得您的软件的最新版。您还可以在出现新版本后,以编程方式更新缓存,如更新缓存部分中所述。
请注意:系统会自动缓存引用清单文件的 HTML 文件。因此您无需将其添加到清单中,但我们建议您这样做。
请注意:HTTP 缓存标头以及对通过 SSL 提供的网页设置的缓存限制将被替换为缓存清单。因此,通过 https 提供的网页可实现离线运行。
六、缓存状态
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);
七、AppCache 事件
正如您所预期的那样,附加事件会用于监听缓存的状态。浏览器会对下载进度、应用缓存更新和错误状态等情况触发相应事件。以下代码段为每种缓存事件类型设置了事件监听器:
function handleCacheEvent(e) {
//...
}
function handleCacheError(e) {
alert('Error: Cache failed to update!');
};
// Fired after the first cache of the manifest.
appCache.addEventListener('cached', handleCacheEvent, false);
// Checking for an update. Always the first event fired in the sequence.
appCache.addEventListener('checking', handleCacheEvent, false);
// An update was found. The browser is fetching resources.
appCache.addEventListener('downloading', handleCacheEvent, false);
// The manifest returns 404 or 410, the download failed,
// or the manifest changed while the download was in progress.
appCache.addEventListener('error', handleCacheError, false);
// Fired after the first download of the manifest.
appCache.addEventListener('noupdate', handleCacheEvent, false);
// Fired if the manifest file returns a 404 or 410.
// This results in the application cache being deleted.
appCache.addEventListener('obsolete', handleCacheEvent, false);
// Fired for each resource listed in the manifest as it is being fetched.
appCache.addEventListener('progress', handleCacheEvent, false);
// Fired when the manifest resources have been newly redownloaded.
appCache.addEventListener('updateready', handleCacheEvent, false);
如果清单文件或其中指定的资源无法下载,整个更新都将失败。在这种情况下,浏览器将继续使用原应用缓存。
八、参考文档
1. [应用缓存初级使用指南](https://www.html5rocks.com/zh/tutorials/appcache/beginner/)
2. [九种浏览器端缓存机制知多少](http://jixianqianduan.com/frontend-javascript/2015/12/28/nine-browser-cache-methods.html)
3. [使用HTTP缓存](http://harttle.com/2017/04/04/using-http-cache.html)
九、缺陷
1、含有manifest属性的当前请求页无论如何都会被缓存
2、更新需要建立在manifest文件的更新,文件更新后是需要2次刷新才能获取新资源
3、更新是全局性的,无法单独更新某个文件(无法单点更新)
4、对于链接的参数变化是敏感的,任何一个参数的修改都会被重新缓存(重复缓存含参页面)index.html和index.html?renew=1会被认为是不同文件,分别缓存
十、适用场景
网友评论