缓存方式分为三种
强缓存
这些看的都是返回值的头部字段
- 浏览器在请求某一资源时,会先获取该资源缓存的header信息,判断是否命中强缓存(cache-control和expires信息),若命中直接从缓存中获取资源信息,包括缓存header信息;本次请求根本就不会与服务器进行通信
1. expires 它的值是一个GMT格式的绝对时间,如Mon, 10 Jun 2015 21:31:12 GMT(如果发送请求的时间在expires之前,那么本地缓存始终有效,如果过了时间那么就会再次向服务端发起请求)
如果cache-control与expires同时存在的话,cache-control的优先级高于expires
协商缓存
如果没有命中强缓存,浏览器会发送请求到服务器,请求会携带第一次请求返回的有关缓存的header字段信息(Last-Modified/If-Modified-Since和Etag/If-None-Match),由服务器根据请求中的相关header信息来比对结果是否协商缓存命中;若命中,则服务器返回新的响应header信息更新缓存中的对应header信息,但是并不返回资源内容,它会告知浏览器可以直接从缓存获取,否则返回最新的资源内容
为什么有了 last-modified还要有Etag
HTTP1.1中Etag的出现主要是为了解决几个Last-Modified比较难解决的问题
- 一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新GET
- 某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说1s内修改了N次),If-Modified-Since能检查到的粒度是s级的,这种修改无法判断(或者说UNIX记录MTIME只能精确到秒)
- 某些服务器不能精确的得到文件的最后修改时间
用Etag能够更加准确的控制缓存,因为Etag是服务器自动生成或者由开发者生成的对应资源在服务器端的唯一标识符。Last-Modified与ETag是可以一起使用的,服务器会优先验证ETag,一致的情况下,才会继续比对Last-Modified,最后才决定是否返回304
试探缓存
如果响应中没有”Cache-Control: max-age”首部,也没有Expires首部,缓存可以计算出一个试探性最大使用期。LM-Factor算法是一种很常用的试探性过期算法,如果文档中包含了最后修改日期,就可以使用这种算法。LM-Factor算法将最后修改日期作为依据,来估计文档有多么易变。实际的LM-Factor算法会计算缓存与服务器对话的时间跟服务器声明文档最后被修改的时间之间的差值,取这个间隔时间的一部分,将其作为缓存中的新鲜度持续时间。缓存通常会为没有任何新鲜周期线索的文档分配一个默认的新鲜周期(通常是一个小时或一天)。有时,比较保守的缓存会将这种试探性新鲜生存期设置为0,强制缓存在每次将其提供给客户端之前,都去验证一下这些数据仍然是新鲜的。与试探性新鲜计算有关的最后一点是——它们可能比你想象的要常见得多。很多原始服务器仍然不会产生Expires和max-age首部。选择缓存过期的默认时间时要特别小心!
LM-Factor算法的逻辑:
如果已缓存文档最后一次修改发生在很久以前,它可能会是一份稳定的文档,不太会突然发生变化,因此将其继续保存在缓存中会比较安全。
- 如果已缓存文挡最近被修改过,就说明它很可能会频繁地发生变化,因此在与服务器进行再验证之前,只应该将其缓存很短一段时间。