强缓存
Pragma 是 HTTP1.0 时期的产物,和后面要说的 cache-control 作用差不多,它的值只能设置为
no-cache
。与 Cache-Control: no-cache 效果一致,即禁用强缓存,只能使用协商缓存。Expires 是HTTP/1.0控制网页缓存的字段,其值为服务器返回该请求结果缓存的到期时间,即再次发起该请求时,如果客户端的时间小于Expires的值时,直接使用缓存结果
Cache-Control 是HTTP 1.1 中增加的字段,被设计用来替代 pragma。cache-control 这个头部字段既可以用在请求头也可以用在响应头中。(
推荐
)
优先级
pragma > Cache-Control > Expires
协商缓存
方法一
- 服务器响应请求时,返回该资源文件在服务器最后被修改的时间
Last-Modified - 客户端再次发起该请求时,携带上次请求返回的Last-Modified值
Last-Modified-Since
服务器的资源最后被修改时间大于If-Modified-Since的字段值,则重新返回资源,状态码为200;否则则返回304,代表资源无更新,可继续使用缓存文件
方法二
- 服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成)
Etag - 客户端再次发起该请求时,携带上次请求返回的唯一标识Etag值,通过此字段值告诉服务器该资源上次请求返回的唯一标识值。
If-None-Match
服务器收到该请求后,发现该请求头中含有If-None-Match,则会根据If-None-Match的字段值与该资源在服务器的Etag值做对比,一致则返回304,代表资源无更新,继续使用缓存文件;不一致则重新返回资源文件,状态码为200
优先级
Etag / If-None-Match > Last-Modified / If-Modified-Since
为什么有了 last-modified 还需要 etag ?
资源在 1 秒内更新,并且在该一秒内访问,使用 last-modified 处理协商缓存无法获取最新资源。本质上的原因还是因为 last-modified 是精确到秒的,无法反映在 1 秒内的变化。
当资源多次被修改后内容不变,使用 last-modified 来处理有点浪费。多次修改资源,其 last-modified 值肯定是会变的,但是如果内容不变我们其实不需要服务器返回最新资源,直接使用本地缓存。使用 etag 就没这个问题,因为同一个资源多次修改,内容一样, hash 值也一样。
使用 etag 更加灵活,因为 etag 并不一定是 hash 值,etag 采用的是弱比较算法,即两个文件除了每个比特都相同外,内容一致也可以认为是相同的。例如,如果两个页面仅仅在页脚的生成时间有所不同,就可以认为二者是相同的。