http缓存策略
url输入后
首次访问或已清除缓存时,(浏览器无缓存数据),(向服务器请求资源),服务器在返回(资源)和(缓存策略),http状态码为200;客户端拿到后将数据和缓存策略缓存到浏览器。
缓存策略
存在于响应头里,
缓存策略主要有:强制缓存 和 协商(对比)缓存,
缓存策略 缓存到浏览器
或者
强制缓存
服务器响应头会有2个字段来表示,expires/cache-control。
- expires
- http1.0的字段,现在浏览器默认使用http1.1,http1.1后使用cache-control代替
- 是一个时间戳,代表资源过期时间。例如:Expires:Sat, 23 May 2009 10:02:12 GMT
- cache-control (请求和响应都可以带cache-control )
-
Request Cache-Control
- "no-cache"
- "no-store"
- "max-age" "=" delta-seconds
- "max-stale" "=" delta-seconds
- "min-fresh" "=" delta-seconds
- "no-transform"
- "only-if-cached"
Response Cache-Control
- "public"
- "private"
- "no-cache"
- "no-store"
- "no-transform"
- "must-revalidate"
- "proxy-revalidate"
- "max-age" "=" delta-seconds
- "s-maxage" "=" delta-seconds
-
cache-control字段解析:
- Cache-Control:public :该 response 为公有缓存
- Cache-Control:private :该 response 为私有缓存
- Cache-Control:no-cache :可以缓存 response,但是必须要经过新鲜度再验证响应后才可以返回缓存。
- Cache-Control:no-store :对应的 resquest/response 不允许存储,这里的不允许存储 即:不允许进行任何持久化存储,如果有存在非持久化存储,也要尽快消除。
- Cache-Control:s-maxage : 意思和 max-age 类似,但是只用于公有缓存,在公有缓存中使用的时候会覆盖 max-age 的值
- Cache-Control:max-age = s :指定相对过期日期,单位为秒
- Expires :指定绝对过期日期
- Cache-Control:max-stale = s :过期后的 s 秒内缓存可以继续使用
- Cache-Control:min-fresh = s :至少在 s 秒内缓存要保持新鲜
- Cache-Control:must-revalidate : 强制缓存重新进行新鲜度验证,因为 http 头中存在一些头域会改变缓存原本的失效时间(比如 request 中的 max-stale),而通过这个头域可以强制缓存进行更新,如果在进行新鲜度验证的时候不能连接到服务器,则返回 504 Gateway Timeout 错误。
- Cache-Control:no-transform : 部分网络代理为了提高性能会对图片等文档进行转换处理(比如压缩),no-transform 可以强制要求网络代理不要对资源进行转换。
- Cache-Control:only-if-cached : 该头域表示不进行与网络相关的交互,只返回已经缓存且满足要求的数据,否则的话返回 504 错误。
- Cache-Control:proxy-revalidate : 和 must-revalidate 类似,只是特定用于公共缓存的。
PS:
- 优先级: max-age > Expires 。
- max-age,max-stale 和 min-fresh 的关系:
- age (已缓存的时间) (服务器首次发出或最后一次被服务器再验证 之后过去的时间),
- 如果 age + min-fresh < max-age,缓存未过期;
- 如果 age + min-fresh >= max-age && age + min-fresh < max-age + max-stale,则虽然缓存过期了,但是缓存继续可以使用,只是在头部添加 110 警告码;
- 如果 age + min-fresh >= max-age + max-stale,则缓存过期且不可使用。缓存使用期 age 的计算可以参考《Http 权威指南》的 7.11.2 节,具体关于缓存使用期和新鲜生存期的问题可以参考 7.11 节。
- no-cache 和 no-store 区别:
- no-cache 实际会进行缓存,只是在缓存响应之前会先进行一次新鲜度再验证(浏览器的 f5 刷新);
- no-store 不会进行缓存,每次都是向获取服务器的最新数据(浏览器的强制刷新)
新鲜度再验证的实现(协商缓存)
有两种实现方式最近修改日期( Last-Modified ) 和实体标签( ETag )验证。(优先级:Etag > Last-Modified)
相关字段
- Last-Modified(响应头 )(最近修改日期)
- If-Modified-Since(请求头)(最近修改日期)
- Etag(响应头 )(唯一标识符)
- If-None-Match(请求头)(唯一标识符)
最近修改日期(If-Modified-Since)验证:
Last-Modified (服务器资源 最近修改日期)>= If-Modified-Since(本地缓存资源 最近修改日期) 则新鲜度过期。也可配合 If-Unmodified-Sinece。
实体标签(ETag)验证:
通过特定标签对比进行验证,比如 ETag 可以用来存版本号,这样就可以通过版本号对比查看新鲜度,可以配合 If-None-Match 来使用,不同则修改过,返回新资源200,否则使用本地缓存304
试探性过期
当 response 中没有 Cache-Control:max-age 和 Expires 的时候,缓存可以计算出一个试探性最大使用期。常用算法 LM—Factor 算法。
缓存位置
缓存主要是对静态资源而言,如图片视频等
- 网络请求:大小 (多少 K, 多少 M 等),
from memory cache
from disk cache
from ServiceWorker
。
- Service Worker、
- Memory Cache、
- 硬盘 Cache、
- 网络请求
几乎所有的 网络请求资源 都会被浏览器自动加入到 memory cache 中。 因为数量很大且不断扩展,只能是个“短期存储”,浏览器的本标签关闭后失效;极端情况下 ,如果一个页面占用内存太大,在关闭前,排在前面的缓存就已经失效了;
cache.delete(resource)
或者容量超过限制,被浏览器全部清空。fetch()
方法获取的资源,即便它并没有命中 Service Worker 缓存,甚至实际走了网络请求,也会标注为 from ServiceWorker
。请求网络
如果一个请求在上述 3 个位置都没有找到缓存,那么浏览器会正式发送网络请求去获取内容。之后容易想到,为了提升之后请求的缓存命中率,自然要把这个资源添加到缓存中去。具体来说:
- 根据 Service Worker 中的 handler 决定是否存入 Cache Storage (额外的缓存位置)。
- 根据 HTTP 头部的相关字段(
Cache-control
,Pragma
等)决定是否存入 disk cache - memory cache 保存一份资源 的引用,以备下次使用。
本文参考于(详情请参考)https://juejin.im/post/5cdbe0a5e51d456e5238ca8f 和 http://www.baitouwei.com/2016/04/20/App-%E7%BC%93%E5%AD%98%E6%96%B9%E6%A1%88%EF%BC%9AHttp-%E7%BC%93%E5%AD%98/