缓存位置
从缓存位置上来说分为四种,并且各自有优先级,当依次查找缓存且都没有命中的时候,才会去请求网络。
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 事件后缓存需要的文件;
用户下次请求的时候查询是否存在缓存,存在直接读取缓存文件,否则就去请求数据。
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
该字段为响应实体的头部字段,指明资源在服务器上最后的修改时间。
过程:
- 浏览器接受有 Last-Modified 字段的响应后会缓存文件和header。
- 浏览器再次请求这个资源的时候,检测到有 Last-Modified 这个header,然后在header中添加 If-Modified-Since 这个字段,值为 Last-Modified 的值。
- 服务器再次收到这个资源请求,会根据 If-Modified-Since 中的值与服务器中这个资源的最后修改时间对比,如果没有变化,返回304和空的响应体,直接从缓存读取,如果 If-Modified-Since 的时间小于服务器中这个资源的最后修改时间,说明文件有更新,于是返回新的资源文件和200。
缺点:
- 如果本地打开缓存文件,即使没有对文件进行修改,但还是会造成 Last-Modified 被修改,服务端不能命中缓存导致发送相同的资源。
- 因为 Last-Modified 只能以秒计时,如果在不可感知的时间内(毫秒级)修改完成文件,那么服务端会认为资源还是命中了,不会返回正确的资源。
ETag
Etag是服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成),只要资源有变化,Etag就会重新生成。
浏览器在下一次加载资源向服务器发送请求时,会将上一次返回的 Etag 值放到request header里的If-None-Match里,服务器只需要比较客户端传来的 If-None-Match 跟自己服务器上该资源的ETag是否一致,就能很好地判断资源相对客户端而言是否被修改过了。
两者对比
- 精确度上,Etag 要优于 Last-Modified,Last-Modified 单位是秒,可能文件一秒内更新了多次而没有返回,并且负载均衡的服务器生成的 Last-Modified 也可能不一样。
- 性能上,Last-Modified 要优于 Etag,因为 Last-Modified 只需要记录时间,而 Etag 还需要计算出一个 hash值。
- 优先级上,服务器会优先考虑 Etag。
缓存机制
- 强制缓存优先于协商缓存进行,若强制缓存(Expires和Cache-Control)生效则直接使用缓存;
- 若强缓存不生效则进行协商缓存(Last-Modified / If-Modified-Since和Etag / If-None-Match);
- 协商缓存由服务器决定是否使用缓存,若协商缓存失效,那么代表该请求的缓存失效,返回200,重新返回资源和缓存标识,再存入浏览器缓存中;生效则返回304,继续使用缓存;
- 若什么策略都没有,浏览器会采用一个启发式算法,通常会取响应头中的 Date 减去 Last-Modified 值的 10% 作为缓存时间。
原文:http://www.duhonghui.top/#/
,