浏览器缓存机制流程
Cache-Control
Cache-Control
用于控制缓存的行为,字段支持同时指定多个指令,多个指令之间通过“,”分隔。
响应报文中支持的 Cache-control 指令
指令 | 说明 |
---|---|
no-store | 不缓存请求和响应的任何内容 |
max-age=[秒] | 缓存的最大有效期 |
s-maxage=[秒] | 缓存的最大有效期,功能与 max-age 相同,区别是: s-maxage 适用于公共缓存服务器 |
public | 表明响应可以被任何对象(包括:发送请求的客户端,代理服务器,等等)缓存 |
private | 表明响应只能被单个用户缓存,不能作为共享缓存(即代理服务器不应缓存它,即使缓存也不应该提供给除特定用户之外的其他用户) |
no-cache | 资源(不管是否过期),客户端都应该向服务器检查更新 |
immutable | 资源(如果未过期)客户端不应向服务器检查更新 |
must-revalidate | 资源(如果已过期),客户端必须向服务器检查更新(其实这已经是很多浏览器的默认行为了) |
no-transform | 不得对资源进行转换或转变。 Content-Encoding , Content-Range , Content-Type 等HTTP头不能由代理修改。(非透明代理可以对图像格式进行转换,以便节省缓存空间或者减少缓慢链路上的流量) |
no-cache
或者public
、private
单独使用均不会让缓存服务器、客户端缓存响应内容,只有max-age
是通知缓存服务器或客户端可以缓存响应内容。但是对于html、css、js、图片等静态资源,如果返回了Etag
或Last-Modified
即使没有指定max-age
,部分客户端也会缓存。- 优先级:
s-maxage
>max-age
> 首部字段Expires
- 如果资源未过期,且未指定
immutable
和no-cache
,在火狐浏览器上执行刷新操作时,会向服务器检查更新,而谷歌浏览器不会(2018-11-11 22:39:54 星期日),由此可见,即使未显式指定immutable
,部分客户端也已经为减少服务器请求做出了优化,不过显式的指定immutable
仍然有必要,可以进一步减少其他浏览器的请求。
请求报文中常用的 Cache-Control 指令
指令 | 说明 |
---|---|
no-store | 不缓存请求和响应的任何内容 |
no-cache | 不使用缓存(即使缓存存在),期望服务器(包括代理服务器)返回最新的内容 |
max-age=[秒] | 缓存的最大有效期。若无缓存:max-age不起作用。若有缓存:如果在有效期,则使用缓存,如果已过有效期,则向原始服务器检查是否有更新,无更新则返回304,客户端继续使用缓存,有更新则返回最新内容 |
only-if-cached | 通常是发送给缓存服务器的指令,缓存服务器应该与原服务器有一套内在的更新缓存的机制。当客户端请求时,如果有缓存则返回,若无缓存则应该返回504状态码 |
max-stale(= [秒]) | 表明客户端愿意接收一个已经失效的资源。可选的秒数表示超过到期时间点的秒数不能大于该给定秒数(当前时间点<=到期时间点+设定值)。省略值表示永远接收 |
min-fresh=[秒] | 表示客户端希望获取一个能在指定的秒数内保持不失效的响应(当前时间<=到期时间点-设定值) |
no-transform | 不得对资源进行转换或转变。 Content-Encoding , Content-Range , Content-Type 等HTTP头不能由代理修改。(非透明代理可以对图像格式进行转换,以便节省缓存空间或者减少缓慢链路上的流量) |
浏览器发送的
Cache-control
指令对最终的资源服务器没有意义,只对中间的缓存服务器起作用(浏览器本地缓存也相当于一个中间的缓存服务器)
总之,协议有协议的规范,具体的客户端、缓存服务器、服务端可能会有不同的实现。
Expire首部
首部字段 Expires
会将资源失效的日期告知客户端。在 Expires
字段值指定的时间之前,响应的副本会一直被保存。当超过指定的时间后,缓存服务器在请求发送过来时,会转向源服务器请求资源。
当首部字段 Cache-Control
有指定 max-age
指令时,max-age
的优先级更高
Pragma首部
Pragma 是HTTP/1.1 之前版本的历史遗留字段。规范定义的唯一形式,如下所示:
Pragma: no-cache
该首部字段属于通用首部字段,但只用在客户端发送的请求中。客户端会要求所有的中间服务器不返回缓存的资源,为了兼容HTTP/1.0,通常会同时发送两个首部字段:
Pragma: no-cache
Cache-Control: no-cache
条件请求 If-None-Match 和 If-Modified-Since
If-Modified-Since
比较资源的更新时间。有更新则返回最新的资源,否则返回304(资源未更新)状态If-None-Match
比较Etag标记。不匹配则返回最新的资源,否则返回304(资源未更新)状态
启发式缓存
当缓存过期时间的响应头一个都没有的时候,浏览器根据响应头中 Date
和 Last-Modified
之间的时间差值,取其值的 10%
作为缓存时间周期。
谷歌浏览器使用了这一机制,而火狐浏览器未使用(没有过期时间的响应头时,向服务器发起缓存协商,如果服务器资源未变更则返回304)
其他缓存相关
谷歌浏览器使用缓存资源时,为什么请求头中有
cache-control: no-cache
谷歌浏览器使用缓存资源时,显示的请求头是生成缓存资源时的请求头。
如果使用
Ctrl+F5
强刷,请求头中会含有cache-control: no-cache
,得到服务器响应的资源后,缓存。再使用普通刷新,浏览器不会再请求服务器,而是直接使用本地缓存,此时显示的请求头中是含有cache-control: no-cache
的。如果清除浏览器缓存后,使用普通刷新,请求头中不会含有
cache-control: no-cache
,得到服务器响应的资源后,缓存。再使用普通刷新,浏览器不会再请求服务器,而是直接使用本地缓存,此时显示的请求头中也是不会含有cache-control: no-cache
的。