浏览器的缓存机制
- 首先通过 cache-control验证强缓存是否可用,如果可用直接只用
- 否则,进入协商缓存,即发送HTTP请求,服务器通过浏览器请求头中的相应字段来验证协商缓存是否可用,如果可用直接使用,否则,返回新的资源和200状态码
浏览器的缓存分为两种,一种是发送HTTP请求,一种是不发送请求
强缓存
强缓存(本地缓存),它不需要发送HTTP请求 ,如果命中缓存,浏览器直接从缓存中读取资源
在HTTP/1.0 中检查强缓存的字段是expires, 在HTTP/1.1 中检查强缓存的字段是cache-control
- EXpires
expires 即过期时间 存在服务端返回的响应头中,告诉浏览器在这个过期时间之前可以直接读取缓存,不需要再次请求1
Expires: Wed, 22 Nov 2020 10:41:00 GMT
表示资源在2020年11月22号10点41分过期,过期了就必须重新发送请求
但~,这个方法有个小bug,那就是服务端的时间和浏览器的时间也许并不是一致
所以服务器返回的过期时间可能就是不准确的,所以这种方式在HTTP1.1版本中就被抛弃了
- Cache-Control
在HTTP1.1中采用 cache-control 字段,它和expires的区别是:expires采用的是具体的时间点来控制缓存,而cache-control采用的是时间时长来控制缓存
1 | max-age=6000 |
表示 这个响应在返回后的7600秒,也就是两个小时后过期,在这两个小时内可以直接使用缓存
- cache-control除了max-age这个属性还有其他一些属性
- public: 客户端和代理服务端都可以缓存,因为一个请求可能要经过不同的代理服务器才能到达目标服务器,那么结果不仅是在浏览器可以缓存,中间的任何代理节点都可以缓存
- private: 只能浏览器缓存,中间代理不能缓存
- no-cache: 跳过当前缓存,发送http请求,即进入协商缓存
- no-store: 不以任何形式进行缓存
- s-maxage: 和max-age相似,区别在于s-maxage是针对代理服务器的缓存时间
如果expires和cache-control同时存在的时候,cache-control会被优先考虑
那么,当资源缓存时间超时了,也就是强缓存失效了,那该怎么办? 答案是:进入协商缓存
协商缓存
强缓存失效后,浏览器在请求头中携带相应的 缓存tag 来向服务器发请求,由服务器来根据这个tag,决定是否使用缓存
缓存tag有两种
last-modified,即最后修改时间
浏览器第一次向服务器发送请求时,服务器接收到后会在响应头中携带一个last-modified字段返回
浏览器接收到后,如果再次请求,会在请求头中携带一个if-modified-since的字段的值就是服务器返回last-modified字段的值(就是最后修改时间),服务器接收到后,会将两个值进行对比,
如果浏览器请求头中的值小于最后修改时间,表示该资源需要更新,即像正常的http请求一样返回资源
否则返回304,告诉浏览器直接使用缓存etag
etag是服务器给文件生成的一个唯一标识,只要这个文件内容有改动,就会生成一个新的标识符,服务器就会通过响应头将这个值传给浏览器
浏览器接收到etag值后,会在下一次请求中,将etag的值,作为if-none-macth这个字段的值放在请求头中传给服务器,服务器接收到后,会将两个值进行对比
如果浏览器请求头中的值和服务器中的etag不同,表示需要返回新的资源了,
否则返回304,告诉浏览器直接使用缓存
总结:
浏览器的缓存机制,首先先通过cache-control验证强缓存是否可用,如果可以用,则直接使用强缓存,否则进入协商缓存,即发送http请求,服务器通过请求头中的if-none-match和if-modified-since字段检查资源更新,如果请求头中这个两个字段的值如果if-none-match的值跟服务器中的etag不一样或if-modifed-since的值小于服务器中last-modified,表示资源需要更新,返回新的资源,否则返回304,告诉浏览器直接使用缓存