http的强缓存以及协商缓存的区别

参考文章: http://www.cnblogs.com/chenqf/p/6386163.html

作者: 木上有水

下方部分图片也同样来自上面的博客

本文章只是对于上文的简单总结,并且结合自己实践发现的细节问题。

上半部分是一个简单的总结:

首先浏览器存在一个缓存数据库,当网络请求成功后,浏览器会根据规则缓存相关数据。

网络第一次请求

当然缓存也分两种,一种是强制缓存,一种是协商缓存

强制缓存:

强制缓存

首先对于强制缓存,有两个header的响应字段表明了强缓存的规则:

(Expires和cache control)字段表明了强缓存的规则。

Expires

Expires的值为服务端返回的到期时间,即下一次请求时,请求时间小于服务端返回的到期时间,直接使用缓存数据。
  
  不过Expires是HTTP1.0的东西,现在默认浏览器均默认使用HTTP 1.1,所以它的作用基本忽略。

另一个问题是,到期时间是由服务端生成的,但是客户端时间可能跟服务端时间有误差,这就会导致缓存命中的误差。

所以HTTP 1.1 的版本,使用Cache-Control替代。

Cache-Control

Cache-Control 是最重要的规则。

常见的取值有private、public、no-cache、max-age,no-store,默认为private。

private: 客户端可以缓存

public: 客户端和代理服务器都可缓存(前端的同学,可以认为public和private是一样的)

max-age=xxx: 缓存的内容将在 xxx 秒后失效
no-cache: 需要使用对比缓存来验证缓存数据(后面介绍)

no-store: 所有内容都不会缓存,强制缓存,对比缓存都不会触发(对于前端开发

协商缓存:

对比缓存,顾名思义,需要进行比较判断是否可以使用缓存。
浏览器第一次请求数据时,服务器会将缓存标识与数据一起返回给客户端,客户端将二者备份至缓存数据库中。
再次请求数据时,客户端将备份的缓存标识发送给服务器,服务器根据缓存标识进行判断,判断成功后,返回304状态码,通知客户端比较成功,可以使用缓存数据。

对比缓存也称协商缓存

第一次网络请求:

第一次网络请求

浏览器再次请求

浏览器再次请求

自己在学习实践中的一点发现:

首先就是如果网络请求没有强缓存字段,会发生什么?

浏览器再次请求

可以看到返回字段既没有expire也没有cache-control字段,可是在chrome浏览器中却是走的强缓存!

而在下方的火狐浏览器当中确实是协商缓存,这是为什么呢?

火狐协商缓存

论坛对于这个问题的讨论

浏览器的缓存有 2 种
一种叫验证性缓存,用 ETag 、 Last-Modified 、 If-None-Match 、 If-Modified-Since 来控制,其特点是会发一个请求给服务器来确认缓存是否有效,如果有效就返回 304 ,省去传输内容的时间
另一种叫非验证性缓存,或者有些人称为强缓存,用 Cache-Control 、 Expires 、 Pragma 来控制,其特点是一但有效就在有效期内不会发任何请求到服务器
从描述也能很容易看出来,非验证性缓存的优先级是高于验证性缓存的,因为有它在就根本不会发请求,自然也没有什么 If-None-Match 之类的东西出现的机会了
你看到的 200 from memory cache 就是非验证性缓存
那么为什么在 Chrome 下会有非验证性缓存呢?就是因为你没有设置 Cache-Control 这个头,没有这个头的话,其默认值是 Private ,在标准中也明确说了:
Unless specifically constrained by a cache-control
directive, a caching system MAY always store a successful response
翻译一下:如果没有 Cache-Control 进行限制,缓存系统可以对一个成功的响应进行存储
很显然, Chrome 是遵守标准的,它在没有检查到 Cache-Control 的时候对响应做了非验证性缓存,所以你看到了 200 from memory cache
同时 Safari 也是遵守标准的,因为标准只说了可以进行存储,而非应当或者必须,所以 Safari 不进行缓存也是合理的
我们可以理解为,没有 Cache-Control 的情况下,缓存不缓存就看浏览器高兴,你也没什么好说的。那么你如今的需求是“明确不要非验证性缓存”,则从标准的角度来说,你必须指定相应的 Cache-Control 头

所以总结来说,如果在chrome当中,响应header不设置cache-control,那么chrome会默认是cache-control:private

但是这也不能一概而论:我的观察就是在chrome中js以及图片文件是默认添加private的而html文件却不会。我觉得这也很好理解,因为一般js是依附于html文件的,如果js文件有修改,一般都是直接修改js文件的hash值,这样只要保证html是最新的,就肯定能保证js文件是最新的。但是图片文件如果有更新,就会发生问题,因为图片的名字一般不是hash。。。

如果想要chrome浏览器每一次请求文件,都走协商缓存一个办法就是:设置cache-control: max-age=0

304

你可能感兴趣的:(http的强缓存以及协商缓存的区别)