离线缓存Manifest

离线缓存 (offline application cache)

离线缓存为的是第一次请求后,根据manifest文件进行本地缓存,并且在下一次请求后进行展示(若有缓存的话,无需再次进行请求而是直接调用缓存),最根本的感觉是它使得WEB从online可以延伸到了offline领域。

可以让Web应用在离线的情况下继续使用,通过manifest文件指明需要缓存的资源

缓存文件(创建manifest文件)

  • 使用utf-8编码
  • 以CACHE MANIFEST开头
  • 三个基本部分
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
CACHE MANIFEST
# version n.n 版本号

CACHE:
#需要缓存的文件
/style/innbar.css
/images/image.jpg

NETWORK:
#此类文件需要从网络访问,每次重新拉取的文件
#指定文件
login.php
#*代表除了CACHE文件其他都要重新拉取
*

FALLBACK:
#离线状况下代替文件、缓存找不到的时候显示它
#当访问/路径时,如果访问失败,自动加载offline.html作为代替
/ offline.html

页面引用manifest文件

在HTML页面中引用manifest

1
<html manifest="sample.appcache">

在服务器添加(描述该消息的媒体类型)

1
mime-type text/cache-manifest

例如:

1
2
在apache/conf/mime.types文件中添加
text/cache-manifest appcache(后缀名)

如何更新

如果有修改资源文件,必须通过manifest文件来刷新被缓存的文件列表

当每一次html加载到manifest时,会对manifest配置文件进行脏检查,当检测到manifest文件被修改后,之前的缓存将会被弃用,转而去根据manifest文件中配置的新内容进行缓存

离线事件

1
2
3
window.applicationCache.addEventListener("progress",(e)=>{
console.log('new file downloaded')
}, false)
名称 描述
checking 检查在manifest里面的文件是否有更新
noupdate 没有找到新文件
downloading 下载中
progress 任何文件被下载这一事件都会被唤起
cached 所有缓存都被下载完
updateready 由于manifest,所有文件被从新下载
obsolete 由于manifest清空,文件找不到
error 各种错误,比如manifest文件格式错误

离线状态

每个manifest缓存都有一个状态, 标示着缓存的情况. 一份缓存清单只有一个缓存状态, 即使它被多个页面引用

window.applicationCache.status

取值 名称 含义
0 UNCACHED 页面完全没有被缓存,可能是没被设定或者尚未被下载
1 IDLE 已经被下载并可访问
2 CHECKING 正在检查是否需要更新
3 DOWNLOADING 发现新版本正在更新
4 UPDATEREADY 已经下载完成,下次离线访问就可以用 随即触发事件 updateready
5 OBSOLETE 缓存清单文件访问失败,此页面会被从缓存中清除

更新缓存方法

applicationCache对象:

  1. status: 返回当前页面的应用缓存的状态, 通常开启应用缓存的页面可能返回1, 其他页面则返回0
  2. update(): 手动触发应用缓存的更新
  3. abort(): 取消应用缓存的更新. 可用于节省有限的网络带宽
  4. swapCache()

如果存在一个更新版本的应用缓存, 那么它将切换过去, 否则将抛出 Uncaught DOMException 错误. 通常, 我们会在updateready事件触发之后手动调用swapCache()方法, swapCache的切换只对后续加载的缓存文件有效, 已经加载成功的资源并不会重新加载

  • JS提供update()和swapCache()直接更新缓存
1
2
3
4
5
6
7
8
<button
onclick= "window.applicationCache.update();">
update applicationCache</button>

window.applicationCache.addEventListener("updateready",(e)=>{
window.applicationCache.swapCache();
console.log('new cache in action')
}, false)
  • 可以使用SetTnterval()定期唤起更新
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 添加事件监听,当监听到本地缓存更新后,进行重载页面,以达到更新的目的。
// 监控
window.onload = function () {
window.applicationCache.onupdateready = function (e) {
console.log(window.applicationCache.status)
// 缓存更新完毕
if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {
// 切换为最新缓存
window.applicationCache.swapCache();
if (confirm('版本更换,是否确认加载?要重新刷新两次')) {
window.location.reload();
}
} else {
console.log('manifest did not change');
}
}
}

检查是否在线

window.navigator.onLine

1
2
3
4
5
6
7
window.addEventListener("online",(e)=>{
console.log('you are now online')
}, false)

window.addEventListener("offline",(e)=>{
console.log('you are now offline')
}, false)

不测路由,只测连接,所以可能联网当不能上网

优势

  1. 完全离线
  2. 资源被缓存,加载更快
  3. 降低server负载
  • 离线浏览 – 用户可在离线时浏览您的完整网站
  • 速度 – 缓存资源为本地资源,因此加载速度较快
  • 服务器负载更少 – 浏览器只会从发生了更改的服务器下载资源

缺陷

  1. 含有manifest属性的当前请求页无论如何都会被缓存
  2. 更新需要建立在manifest文件的更新,文件更新后需2次刷新页面才能获取新资源

    若manifest更新,则只有在第二次访问时才能显示更新的内容,第一次仍显示的是原(app cache)缓存中的内容

  3. 更新是全局性的,无法单独更新某个文件(无法单点更新)

    比如修改manifest文件,所有在缓存列表的文件都需要重新去下载(可以配合http缓存304做到只去下载更新的文件)

  4. 对于链接的参数变化是敏感的,任何一个参数的修改都会被master重新缓存(重复缓存含参页面)

    index.html和index.html?renew=1会被认为是不同的文件,分别缓存。所以当页面有参数的时候不建议使用manifest、

使用场景

  1. 单地址页面(没有参数的)
  2. 对实时性要求不高的业务
  3. 离线webapp