从缓存位置上来说分为四种,并且各自有优先级,当依次查找缓存且都没有命中的时候,才会去请求网络。
Service Worker / Memory Cache / Disk Cache / Push Cache
Service Worker
Service Worker 是运行在浏览器后台的独立线程,可以用来实现缓存。由于 Service Worker 中涉及到请求拦截,所以必须是 Https协议的请求。Service Worker 的缓存与浏览器其他内建的缓存机制不同,它可以让我们自由控制缓存哪些文件、如何匹配缓存、如何读取缓存,并且缓存是持续性的。
当 Service Worker 没有命中缓存的时候,我们需要去调用 fetch 函数获取数据。也就是说,如果我们没有在 Service Worker 命中缓存的话,会根据缓存查找优先级去查找数据。但是不管我们是从 Memory Cache 中还是从网络请求中获取的数据,浏览器都会显示我们是从 Service Worker 中获取的内容。
Service Worker 实现缓存一般分为三步:
首先注册 Service Worker;
监听到 install 事件后缓存需要的文件;
用户下次请求的时候查询是否存在缓存,存在直接读取缓存文件,否则就去请求数据。
Memory Cache
内存中的缓存。一般网页中已经抓取到的资源会被放入内存缓存,比如已经下载的样式、脚本、图片等等。
内存缓存虽然读取高效,可是缓存持续性很短,会随着进程的释放而释放。一般我们关闭tab页面以后缓存就会被释放。
内存缓存在缓存资源时并不关心返回资源的HTTP缓存头Cache-Control是什么值,同时资源的匹配也并非仅仅是对URL做匹配,还可能会对Content-Type,CORS等其他特征做校验。
内存缓存中有一块重要的缓存资源是preloader相关指令,例如<link rel="preload" href="sintel-short.mp4">,
preload预加载也是前端优化的常用手段。
Disk Cache
硬盘中的缓存。相比内存缓存读取速度更慢,但是没有任何限制,容量和生命周期都更好。它会根据 HTTP Herder 中的字段判断哪些资源需要缓存,哪些资源可以不请求直接使用,哪些资源已经过期需要重新请求。
浏览器对 memory Cache 和 disk cache 存储优先级:
* 对于大文件来说,大概率是不存储在内存中的,反之优先
* 当前系统内存使用率高的话,文件优先存储进硬盘
Push Cache
推送缓存是Http2.0才有的,当以上的缓存没有命中才会被使用。他只会在 Session 中存在,一旦会话结束就被释放,缓存时间也很短暂。在Chrome浏览器中只有5分钟左右,同时它也并非严格执行HTTP头中的缓存指令。
关于推送缓存的一特性:
* 所有的资源都能被推送,并且能够被缓存,但是 Edge 和 Safari 浏览器支持相对比较差
* 可以推送 no-cache 和 no-store 的资源
* 一旦连接被关闭,Push Cache 就被释放
* 多个页面可以使用同一个HTTP/2的连接,也就可以使用同一个Push Cache。这主要还是依赖浏览器的实现而定,出于对性能的考虑,有的浏览器会对相同域名但不同的tab标签使用同一个HTTP连接。
* Push Cache 中的缓存只能被使用一次
* 浏览器可以拒绝接受已经存在的资源推送
* 你可以给其他域名推送资源
缓存过程
1.浏览器每次发起请求,都会先在浏览器缓存中查找该请求的结果以及缓存标识
2.浏览器每次拿到返回的请求结果都会将该结果和缓存标识存入浏览器缓存中
根据是否需要向服务器重新发起HTTP请求,分为 强缓存和*协商缓存*两种缓存策略
缓存策略
浏览器缓存策略分为两类:强缓存和协商缓存,缓存策略通过 HTTP 头部 Header 来设置。
强缓存
不会向服务器发送请求,直接从缓存中读取资源,在chrome控制台的Network选项中可以看到该请求返回200的状态码,并且Size显示from disk cache或from memory cache。强缓存可以通过设置两种 HTTP Header 实现:Expires 和Cache-Control。
Cache-Control
可以通过 Cache-Ccontrol 控制缓存的工作机制。
--指令--说明public所有内容都将被缓存private所有内容只有客户端会被缓存,中间节点不允许缓存no-cache客户端缓存内容,使用缓存则需要经过协商缓存来验证决定no-store所有内容都不会被缓存,即不使用强制缓存,也不使用协商缓存max-agemax-age=xxx (xxx is numeric)表示缓存内容将在xxx秒后失效s-maxage同max-age作用一样,只在代理服务器中生效(比如CDN缓存),如果存在s-maxage,则会覆盖掉max-age和Expires headermax-stale能容忍的最大过期时间,如果没有指定,那么说明浏览器愿意接收任何age的响应min-fresh能够容忍的最小新鲜度,min-fresh标示了客户端不愿意接受新鲜度不多于当前的age加上min-fresh设定的时间之和的响应。可以结合多个指令,实现不同的缓存功能:
Expires
指定缓存资源的过期时间(),Expires 是服务器响应实体首部字段。如果在 Cache-Control 响应头设置了 "max-age" 或者 "s-max-age" 指令,那么 Expires 头会被忽略。同时注意,如果修改本地时间打过 Expires 的时间会造成缓存失效。
示例:
Expires: Wed, 21 Oct 2015 07:28:00 GMT
两者对比
两者差别不大,区别就在于 Expires 是http1.0的产物,Cache-Control 是http1.1的产物,两者同时存在的话, Cache-Control 优先级高于 Expires ,现阶段 Expires 更多的是用于兼容的写法。
协商缓存
协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程。协商返回会有两种状态:
1.协商缓存生效,返回 304 Not Modified 状态码:
2.协商缓存失败,返回 200 状态码:
协商缓存可以通过设置 Last-Modified 和 ETag 实现:
Last-Modified
该字段为响应实体的头部字段,指明资源在服务器上最后的修改时间。
过程:
缺点:
ETag
Etag是服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成),只要资源有变化,Etag就会重新生成。
浏览器在下一次加载资源向服务器发送请求时,会将上一次返回的 Etag 值放到request header里的If-None-Match里,服务器只需要比较客户端传来的 If-None-Match 跟自己服务器上该资源的ETag是否一致,就能很好地判断资源相对客户端而言是否被修改过了。
两者对比
缓存机制