浏览器缓存阶段
- 强缓存阶段
- 启发式缓存阶段
- 协商缓存阶段
浏览器缓存机制
缓存流程
如上图,浏览器在首次访问网站的时候(第一次发起HTTP请求),由于浏览器缓存没有该网站信息,所以浏览器直接发起HTTP请求。
网站(服务器)处理请求后,返回的response header中,包含请求结果和缓存规则,这里的缓存规则也就是后面会讲到的强缓存和协商缓存的相关字段。
当浏览器第二次访问该网站的时候,就会结合缓存信息进行相应的判断,判断是否使用强缓存、协商缓存
强缓存 —— 直接使用缓存
相关字段:Cache-Control、expires
强缓存利用HTTP头中的Expires和Cache-control连个字段来控制,这两个字段用来表示资源的缓存时间。
Expires
http1.0规范,Expires的值是一个绝对时间GMT格式的时间字符串
例如:Expires: Fri Nov 08 2019 09:39:47 GMT+0800 (中国标准时间),表示这个资源过期的时间是2019年11月8日的09:39:47,只要发送请求的时间在expires之前,资源就有效
PS:浏览器或服务器其中一端时间错误,影响缓存准确性
Cache-control
http1.1中出现的,主要利用该字段的max-age值来判断,max-age的值是一个相对时间。
例如:Cache-control: max-age=300,表示资源有效期300秒。
Cache-control字段的其他值
不同取值可以组合使用,组合使用方式
各值存在优先级,在此不做展开
优先级:Cache-control > Expires
协商缓存 —— 强缓存失效
相关字段: Etag、Last-Modified
协商缓存是在强缓存失效的时候,客户端将协商缓存相关的字段,转换成特殊字段加到请求头里,交由服务器来判断缓存资源是否可用。
个人理解:注意,这里指的强缓存失效,并不是缓存失效,只是服务器设定的一个有效期,过了这个时间,客户端应该需要向服务器询问,本地的缓存是否过期,是否需要更新。
对于Etag和Last-Modified字段,在请求服务器时,会转换成If-None-Match和If-Modified-Since放到请求头中。也就是,第一次请求,服务器返回Etag和Last-modified字段,后续请求会带上If-None-Match和If-Modified-Since字段去询问服务器。
Etag / If-None-Match
Etag 是资源的标识符。
可以保证每一个资源是唯一的,资源变化都会导致 Etag 变化。服务器根据浏览器上送的 If-None-Match 值来判断是否命中缓存
Last-Modified / If-Modified-Since
Last-Modified 是一个时间标识该资源的最后修改时间。
例如 Last-Modify: Thu,31 Dec 2037 23:59:59 GMT
优先级:Etag > Last-Modified
为什么要有Etag
Last-Modified似乎已经可以完成协商缓存的作用,为什么需要Etag。并且Etag的优先级更高呢?
- 一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新GET;
- 某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说1s内修改了N次),If-Modified-Since能检查到的粒度是s级的,这种修改无法判断(或者说UNIX记录MTIME只能精确到秒);
- 某些服务器不能精确的得到文件的最后修改时间。
浏览器缓存机制流程图
启发式缓存
- 没有任何关于缓存的字段 —— 不设置任何缓存策略
- 常会取响应头中的 Date 减去 Last-Modified 值的 10% 作为缓存时间