离线缓存manifest用于前端优化

离线缓存

离线缓存又叫“ApplicationCache”,是从浏览器缓存中分出来一块缓存区,用来存储一定的资源。它是HTML5的新特性。你可以使用它将构成web应用程序的资源,如HTML、css、JavaScript、图片等存储到本地缓存中,这样不仅可以使以后进来时更加方便,还可以在离线状态时“无差别”继续使用web应用!

离线缓存和普通的浏览器网页缓存的区别:

  • 缓存目标:任何网页都会自动强制缓存当前网页(无刷新情况下的上一个页面),而离线缓存针对整个web应用程序,且只保存你明确指定的资源。
  • 离线缓存的安全性高于浏览器网页缓存!
  • 离线缓存在无网络状态下几乎也能正常运行!

    离线缓存的特性

    1、对象

HTML5离线缓存有一个专门的对象(JavaScript实现),也就是俗称的ApplicationCache API。我们可以通过控制它来动态控制缓存 —— 它可以触发一系列与缓存状态有关的事件。而且它和缓存宿主对象的关系是一一对应的。

比较离谱的是:离线缓存和H5一样,不被IE9及以下的浏览器支持。我们可以用以下代码检测当前浏览器是否支持离线缓存:

1
2
3
4
5
if(window.applicationCache){
console.log("浏览器支持离线缓存")
}else{
console.log("浏览器不支持离线缓存")
}
2、属性

applicationCache对象是有status属性的,它可以返回当前applicationCache的状态 —— 这是很有用的,本文将介绍另一种更新缓存的方法,就和此有关:

  • 0:未缓存(UNCACHED)
  • 1:空闲(IDLE),应用缓存已是最新,并且没有被标记为“废弃”
  • 2:检查中(CHECKING),此时applicationCache对象已经和一个应用缓存关联了
  • 3:下载中(DOWNLOADING)
  • 4:更新准备就绪(UPDATEREADY),此状态表示缓存不是最新的,而且可以更新
  • 5:“废弃”(OBSOLETE),该缓存已过期
    其中“ IDLE ”是缓存中最典型的状态,它说明当前应用程序的所有资源都已经缓存,而且不需要更新。
3、事件

对于不同的状态,ApplicationCache API提供了特定的事件和回调特性:

  • checking:当检查更新,或者第一次下载manifest文件时,首先会被触发
  • noupdate:当检查到manifest文件不需要更新时触发
  • downloading:第一次下载或更新manifest文件时触发,而且全程只触发一次!
  • progress:在manifest文件下载过程中可被周期性触发
  • cached:manifest文件下载完毕而且缓存成功后触发
  • updateready:当manifest文件下载完毕后触发,此后可通过重新加载页面读取缓存文件或通过swapCache()方法更新缓存文件
  • obsolete:请求资源出错(如访问manifest缓存文件404或410)时触发
    离线缓存的实现(应用)
    它是通过配置一个配置文件manifest进行的,文首链接文章中已经说明:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    CACHE MANIFEST
    # 2020-10-28 v1.1.0
    1.html
    /css/ss1.css
    /img/cur.png
    /img/loading.gif
    /img/loading2.gif
    /img/QQ图片20190521233736.jpg
    /img/Cache_46072b3594a9a6b5..jpg
    /img/牌.png
    /img/logo.png
    /js/ss1.js

    NETWORK:
    * # 这里星号表示除缓存文件外的全部资源

    FALLBACK:
    / /1.html
    它实际上是一个文本文件,列出了所有需要执行操作的资源!第一行必须以CACHE MANIFEST开头。

manifest文件实际上只包含三个部分:需要缓存的、不能缓存的,和无网时的代替文件:

  • CACHE MANIFEST - 在此标题下列出的文件将在首次下载后进行缓存(到本地)(:以后进来都不请求了直接拿
  • NETWORK - 在此标题下列出的文件需要每次与服务器连接请求资源,且不会被缓存
  • FALLBACK - 在此标题下列出的文件规定当页面无法访问时的回退页面(比如 404 页面),这里代码中的意思是“当无法建立因特网连接时,用 “1.html” 替代 / (根)目录下的所有文件”

离线缓存不只是前端的事:它需要服务器的支持!
项目中如果使用的Tomcat服务器,需要更改web.xml文件(conf目录下):
注意: 代码中extension的值必须和你自己写的manifest文件的后缀名一致!

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

注意:
如果manifest文件以及manifest文件所列出的资源无法加载,整个缓存的更新过程则无法进行,浏览器会使用最后一次成功的缓存。
CACHE、NETWORK、FALLBACK在manifest中的顺序是任意的,每一部分可以出现一次或多次。
CACHE是必需的,NETWORK和FALLBACK是可选的。

如何引用?

在web应用程序中每个需要缓存的页面都需要包含manifest文件的引用:

1
<html manifest="cache.appcache"><!-- manifest属性值为manifest文件路径+名称 -->

这里的路径可以使用绝对URL(http/https开头),也可以使用相对路径!

离线缓存的更新

有一件很可怕的事:服务器资源更新了但是用户看不到!这是由于设置了离线缓存但是缓存文件资源没有更新导致的!

更新HTML5离线缓存目前有两种比较常用的方法:

  • 修改manifest文件
    在上面代码中,你会发现第二行第一个字符是“#”:这表示注释。但是它也可以满足其他用途 —— 修改日期和版本号的注释行是一种使浏览器重新缓存资源文件的方法!
    (时间和版本号注释行通常在manifest文件的第二行)

  • 使用applicationCache对象的update()事件更新资源
    比较疑惑的是:这种方式必须也要更新manifest文件!
    使用这种方式触发时需要先调用事件:applicationCache.update() ,这将使浏览器尝试更新用户的缓存。然后判断当 applicationCache.status 处于 UPDATEREADY 状态(前面说过的“更新准备就绪”)时,调用 applicationCache.swapCache() 即可将原缓存换成新缓存:

    1
    2
    3
    4
    5
    6
    var appCache=window.applicationCache;
    appCache.update();
    //...
    if(appCache.status==window.applicationCache.UPDATEREADY){
    appCache.swapCache();
    }

    上面这段代码是通过按钮点击来手动执行资源更新检测 —— 这也很常见!

当然,上面这段代码可以放到head中每次执行:

1
2
3
4
5
6
7
8
9
10
window.addEventListener("load",function(e){
window.applicationCache.addEventListener("updateready",function(e){
if(window.applicationCache.status==window.applicationCache.READY){
window.applicationCache.swapCache();
if(confirm("资源有更新,是否重新装载?")){
window.location.reload();
}
}
})
})