资讯专栏INFORMATION COLUMN

浏览器的缓存(2)

impig33 / 1361人阅读

摘要:的兼容性由于是现代的技术,以下的古老浏览器是不支持的。当然也可以手动指定文件这些浏览器都不能直接使用缓存,即可能会要求你重新验证,或者直接使用服务器文件。

亲,如果你还在为你没网打开不网页而烦恼吗?
亲,你还在为你web服务器复杂的配置项而蛋疼吗?
不要998,manifest抱回家~
manifest自H5横空出世以来给前端网页的浏览带来了翻天覆地的变化,以前我们的网页必须在有网的前提下打开(主要还是打开HTML), 但是现在,我们可以offline 浏览。 可以算是实现web app的一个特技。
manifest的兼容性 IE9+. 由于是现代的技术,IE9以下的古老浏览器是不支持的。所以,manifest主要应用是针对现代浏览器或者手机端更多一些。

入门manifest

浏览器检测你是否使用manifest特技时,是检测html标签.


当解析你的HTML时,发现存在manifest文件时,则会进行如下的操作:

(from alloy team)
manifest文件可以是任意后缀比如. usable.manifest||usable.mf等,但是他的MIMEtype必须设置正确.
记住,这个时候manifest会将HTML文件也一并保存,这需要注意。

书写manifest文件

一个简单的demo:

CACHE MANIFEST
#version 1.3
/public/static/index.css
/public/static/header.css
NETWORK:
*
FALLBACK:
/userInfo/ /404.html
#额外需要添加的缓存文件
CACHE:
images/logo1.png
images/logo2.png

基本样式就是上述

CACHE MANIFEST/CACHE

第一行必须是指定头即, "CACHE MANIFEST"(不能有其他的). 表示哪些文件需要缓存。如果是相对路径则是,在manifest文件所在的目录下。而且,不能使通配符!!!(tm 你是还不是傻). 所以一般而言只能一个一个配置.

CACHE MANIFEST
#相对于manifest文件所在的目录
    ./index.css 

注释: 注释使用#+"info"
可以对缓存文件性质进行适当的说明。缓存后的文件,就会被带上Expires的头,表示可以不经过服务器验证直接使用本地文件。所以,返回status Code 为 200.
另外,CACHE 定义的文件内容,和CACHE MANIFEST 是一个效果,只是跟在CACHE MANIFEST之后,就可以省略书写CACHE,你添加上也可以。

CACHE MANIFEST
#version 1.3
CACHE:
/favicon.ico

而且CACHE可以放在文中的任意位置,不过一般都是放开头,或者省略.

CACHE MANIFEST

# 缓存文件
index.html
css/style.css

NETWORK:
*

# 额外的需要缓存的文件
CACHE:
images/logo1.png
images/logo2.png
images/logo3.png
NETWORK

这里设置不使用缓存的文件,可以使用通配符"*"等。
* 表示,除了CACHE MANIFEST定义的文件之外的文件都不能被缓存。
当然也可以手动指定文件:

NETWORK
*
http://www.example.com/index.html
http://www.example.com/header.png
http://www.example.com/blah/blah

这些浏览器都不能直接使用缓存,即,可能会要求你重新验证,或者直接使用服务器文件。

FALLBACK

这个tag,可用可不用。 用来表示,指定文件无法加载时,使用另外的文件代替。参数有两部分构成,第一部分是指定资源(可能存在文件未加载),第二部分是替代资源

FALLBACK:
/index.html /404.html
/static/* /404.html
/images/* /NotFound.jpg

当index.html无法加载时,使用404.html代替. 这里有个要求,两个路径必须使用相对路径并且与清单文件同源。

SETTINGS

这算是一个附加属性吧。通常设置内容就只有:

SETTINGS:
prefer-online

表示,在有网的情况下,会先访问服务器的文件,看有没有更新,相当于设置了Cache-Control:max-age=0,must-revalidate; + ETag||Last-modified. 不过,比较stupid的是,只有FF(Opera 12)支持.

服务器设置manifest

而在服务器端,需要对manifest文件的MIME设置正确。这里以nginx为例, 具体设置一下MIME type

type{
  image/gif                             gif;  
  image/jpeg                            jpeg jpg;  
  application/x-javascript              js;  
  }

详情可以参考: manifest文件配置

自动生成manifest文件配置

这里以gulp为例。 可以在npm里面很容易找到gulp-manifest这个生成插件.
直接下载:

npm install gulp-manifest --save-dev

然后在gulpfile里面配置:

gulp.task("manifest", function(){
  gulp.src(["build/**"], { base: "./" })
    .pipe(manifest({
      hash: true,
      preferOnline: true,
      network: ["*"],
      fallback:["/images/* /404.html"]
      filename: "app.manifest",
      exclude: "app.manifest"  //不保存manifest,不过有没有效果一样
     }))
    .pipe(gulp.dest("./"));
});

接着就会在目录下生成app.manifest文件,里面就是一些基本的文件格式了。另外如果你想查看你电脑有多少网页是manifest,可以直接访问 chrome://appcache-internals/.

manifest的坑点

manifest对于单页应用可谓是如鱼得水,但是,到了多页应用的层面,他的bug真的是暴露无遗。

1.页面保存的复杂度,
2.文件的及时更新,
3.缓存文件的设置, 
4.死都会保存HTML,
5.文件下载出错,则这次更新缓存失败,
6.覆盖所有缓存头,除了Cache-Control:no-store
7.在Android 4.4的webview里,关闭之后会丢失cache
8.IE10不能很好的支持FALLBACK部分.

所以,appCache的bug也是非常多的。
例如,长尾更新问题,当你的页面保持在线的时候,是无法检测文件已经更新,除非你reload页面,但是用户并不知道你已经更新,所以这里我们需要引进js的提供的缓存检测API.

window.applicationCache

这是前端能够摸到缓存最真实的API。我们可以通过这个API接口获取到我们很多想要的东西:

var appcache = window.applicationCache;
console.log(appcache.status); //检查当前缓存状态
console.log(appcache.IDLE); //缓存状态常量,下面解释
常用的属性有:
属性名 explanation
status 当前缓存状态,为Number类型. 为0~5
UNCACHED(0) 浏览器未缓存文件
IDLE(1) 空闲状态,浏览器已经全部缓存
CHECKING(2) 页面正在检查当前离线缓存是否需要更新
DOWNLOADING(3) 页面正在下载需要更新的缓存文件
UPDATEREADY(4) 页面缓存更新完毕
OBSOLETE(5) 缓存已经过期
常用的方法:
window.applicationCache.update()  
//update方法调用时,页面会主动与服务器通信,检查页面当前的缓存是否为最新的,如不是,则下载更新后的资源

window.applicationCache.swapCache()  //updateready后,更新到最新的应用缓存

通常结合上述两个方法和相应的属性我们可以手动触发文件的更新(前提是 manifest文件改动).

var appCache = window.applicationCache;

appCache.update(); 
//检查更新

if (appCache.status == window.applicationCache.UPDATEREADY) { 
//如果存在更新,并且已经下载ok,则替换浏览器缓存
  appCache.swapCache();  
}

但是,此时页面并不能用上最新的文件,只是浏览器的缓存已经改变,网页实际内容还是原来的内容,还需要手动进行reload,才能进行更新文件

window.addEventListener("load", function(e) {

  window.applicationCache.addEventListener("updateready", function(e) {
    if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {
      if (confirm("文件有更新,手否重新加载文件")) {
        window.location.reload();
      }
    } else {
      //如果,拒绝则不刷新网页
    }
  }, false);

}, false);
cache相关事件

相关事件有: checking,downloading,updateready,obsolete,cached,error,noupdate,progress.
对照上述的status就可以很容易知道每个事件对应的效果是神马。 需要说的就是:

progress: 当浏览器在下载资源时,每下载成功一次,就会触发一次
noupdate:当浏览器检查更新之后发现没有资源更新的时候触发这个事件
error: 更新出错时会触发,比如文件无法正常下载,manifest文件被删除.

其实,使用manifest的时候,无外乎就是3种常用状态

第一次访问页面时

再次访问页面时,没有更新

再次访问页面时,有更新

每次,触发的事件顺序为:

行为 事件顺序
第一次访问页面 checking->downloading->progress(多次)->cached
再次访问时,没有更新 checking->noupdate
再次访问时,有更新 checking->downloading->progress(多次)->updateready

上面看不懂没关系,我们可以看看更直观的Console的内容。

第一次访问页面时

checking->downloading->progress(多次)->cache

2. 再次访问页面时,没有更新

checking->noupdate

3. 再次访问页面时,有更新

checking->downloading->progress(多次)->updateready

浅谈manifest

其实,manifest就是为了离线应用而生的,但是由于设计之初,没有很好的规范,导致现在manifest的bug,真的超级多。
看到whatwg上面说的一句话,真的更加蛋疼.

This feature is in the process of being removed from the Web platform. (This is a long process that takes many years.) Using any of the offline Web application features at this time is highly discouraged. Use service workers instead.

意思就是让你不要用manifest,应该他迟早要被fire的,但是,这一天还有很多年,很多年。 另外一个替代方案就是使用SS,但是兼容性,真的极其差。几乎现在的浏览器都没有实现(除了布道师FF实现了部分). 现在我们真的很尴尬,不过,目前的情况而言,in my opinion, 是十分推荐使用的(也没有其他的办法了). 那该怎么做,才能将manifest的Bug减到最低呢?
推荐的做法是将逻辑页面和用户数据给分离开。 逻辑页面使用app cache,而用户数据可以保存在web Storage || indexDB 等浏览器数据库里,动态更新data时,使用web Socket,ajax,SSE等技术.

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/61784.html

相关文章

  • 一篇文章理解Web缓存

    摘要:的数据将一直保存在浏览器内,直到用户清除浏览器缓存数据为止。它也是一个被标准废弃的功能,主要是通过文件来标注要被缓存的静态文件清单。尽管也有文件,但是与应用缓存却完全不同。另外,用来控制缓存的使用。 最近把前端缓存重新整理了一下,从整体的层面上把前端所有能用的缓存方案梳理了一遍。同时,对于http缓存,使用了表格的方案,使得原先晦涩难记的特性变得清晰明了。特记录于此,若有什么欠缺,也望...

    tangr206 评论0 收藏0
  • 一篇文章理解Web缓存

    摘要:的数据将一直保存在浏览器内,直到用户清除浏览器缓存数据为止。它也是一个被标准废弃的功能,主要是通过文件来标注要被缓存的静态文件清单。尽管也有文件,但是与应用缓存却完全不同。另外,用来控制缓存的使用。 最近把前端缓存重新整理了一下,从整体的层面上把前端所有能用的缓存方案梳理了一遍。同时,对于http缓存,使用了表格的方案,使得原先晦涩难记的特性变得清晰明了。特记录于此,若有什么欠缺,也望...

    zlyBear 评论0 收藏0
  • 浅谈览器缓存

    摘要:最近在项目中遇到了浏览器因缓存问题未能成功向后端发送类型请求的,然后顺藤摸瓜顺便看了看缓存的知识,觉得有必要总结一下。是服务器响应消息头字段,在响应请求时告诉浏览器在过期时间前浏览器可以直接从浏览器缓存取数据,而无需再次请求。 最近在项目中遇到了IE浏览器因缓存问题未能成功向后端发送GET类型请求的bug,然后顺藤摸瓜顺便看了看缓存的知识,觉得有必要总结一下。 在前端开发中,性能一直都...

    godruoyi 评论0 收藏0
  • 浅谈览器缓存

    摘要:最近在项目中遇到了浏览器因缓存问题未能成功向后端发送类型请求的,然后顺藤摸瓜顺便看了看缓存的知识,觉得有必要总结一下。是服务器响应消息头字段,在响应请求时告诉浏览器在过期时间前浏览器可以直接从浏览器缓存取数据,而无需再次请求。 最近在项目中遇到了IE浏览器因缓存问题未能成功向后端发送GET类型请求的bug,然后顺藤摸瓜顺便看了看缓存的知识,觉得有必要总结一下。 在前端开发中,性能一直都...

    shiina 评论0 收藏0
  • 览器缓存看这一篇就够了

    摘要:浏览器缓存作为性能优化的重要一环,对于前端而言,重要性不言而喻。根据浏览器发送的修改时间和服务端的修改时间进行比对,一致的话代表资源没有改变,服务端返回正文为空的响应,让浏览器中缓存中读取资源,这就大大减小了请求的消耗。 浏览器缓存作为性能优化的重要一环,对于前端而言,重要性不言而喻。以前总是一知半解的,所以这次好好整理总结了一下。 1、缓存机制 首先我们来总体感知一下它的匹配流程,如...

    tinysun1234 评论0 收藏0
  • 掌握缓存,不再让你蓝瘦香菇

    摘要:数据库缓存当应用逻辑较为复杂,频繁进行数据库查询,很容易导致数据库不堪重荷。单位为指定设置缓存最大的有效时间,定义的是时间长短。 本文内容概要: 1 Web缓存是什么?为什么要使用它?2 Web缓存的类型3 浏览器缓存的基本知识3.1 Expires3.2 Last-modified3.3 Cache-Control3.4 ETag4 浏览器缓存机制4.1 强缓存应用4.2 协商缓存应...

    Cristic 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<