缓存步骤

  • 浏览器发现缓存无数据 于是就发送请求 想服务器获取资源
  • 服务器响应请求 返回资源 同时标记资源的有效期
  • 浏览器缓存资源 留待下次使用

    服务器的缓存策略

    从服务拿到的资源服务器会通过response headers里的字段控制他们的有效期
    Cache-Control:max-age=2592000
    表示资源可以缓存2592000s, 这个时间的起点是响应报文的的创建时间(即Date字段),而不是客户端收到报文时间,也就是说包含了传输的时间

Cache-Control: no-store
不允许缓存

Cache-Control: no-cahce
允许缓存 但是使用缓存的时候必须去浏览器验证

Cache-Control:must-revalidate
允许在资源有效期使用 过期了就必须去服务器验证

客户端的缓存策略

现在你随便找一个页面 点击刷新(硬性重新加载 or 清除缓存并重新加载) ,你再看一些图片资源 就不再是普通刷新时的200 (from memory cache)了。 而只是200 。 这是为什么呢?

其实不止服务器可以设置Cahce-Control 浏览器也是可以的, 当我们点击硬性重新加载的时候浏览器会重新发送请求,并且在请求头上加上Cache-Control:no-cache字段 ,服务器看到就会生成一个新的response给浏览器

条件请求

浏览器用 Cache-Control 做缓存控制 值能刷新数据 不能很好的利用缓存数据 又因为缓存会失效 使用前还必须要服务器验证是否是最新版

那么应该怎么做呢

浏览器可以使用两个连续请求组成验证动作: 先是一个HEAD 获取资源的修改时间等元信息 然后和缓存数据做比较 然如果没有改动就使用缓存,节省网络流浪 否则就发送一个GET 获取最新版本

但是这样两个请求的的成本太高了,所以http就定义了一系列 if 开头的条件请求字段 专门来验证字眼是否过期,把两个请求的工作合在了一个请求中 而且验证的责任也交给了服务器 浏览器坐享其成

条件请求一共有五个字段, 我们最常用的事 If-Modified-Since 和 If-None-Match 两个 需要第一次响应的报文提供 Last-modified E-tag两个字段。 然后第二次的时候就可以带上缓存的原值 来验证资源是否是最新的

如果资源没变 服务器就回应一个 ‘304 not Modified’ 表示缓存依然有效 浏览器就可更新一下有效期 然后就可以放心大胆地使用了

http的缓存控制 - 图1

ETag是什么呢? Etag是资源的唯一标识 主要用来解决修改时间无法准确区分文件变化的问题
比如一个文件在一秒内修改了很多次。 但是因为修改时间就是秒级, 所以这一秒内新版本无法区分
在比如一个文件定期更新 但有时候内容其实没有变化, 用修改时间就会误以为发生了变化 传送给浏览器造成宽带浪费

使用Etag就可以精确的识别资源的变动情况 让浏览器能够更有效的利用缓存

ETag有 强 弱 之分

强的Etag要求资源在字节级别必须完全相符, 弱Etag在值的前有 W/ 标记 只要求资源在语义上没有变化 但内部可能发生了变化 (例如html内部标签的顺序调整 或者多了几个空格)

https://time.geekbang.org/column/article/106804