强缓存是否新鲜 = 缓存新鲜度 > 缓存使用期
强缓存是否新鲜取决于两个关键词:缓存新鲜度和缓存使用期。
缓存新鲜度 = max-age || (expires - date)
上述公式不难理解:当 max-age 存在时缓存新鲜度等于 max-age 的秒数,是一个时间单位,就像保质期为 6 个月一样。当 max-age 不存在时,缓存新鲜度等于 expires - date 的值,expires 我们应该已经熟悉,它是一个绝对时间,表示缓存过期的时间,那么下面主要介绍下首部字段 date。
Date 表示创建报文的日期时间,可以理解为服务器(包含源服务器和代理服务器)返回新资源的时间,和 expires 一样是一个绝对时间,比如
date:Wed, 25 Aug 2021 13:52:55 GMT
那么过期时间(expires)减去创建时间(date)就可以计算出浏览器真实可以缓存的时间(默认已经转化为秒数),即缓存的保质期限(缓存新鲜度)。
至此,以上关于缓存新鲜度的计算公式便介绍完了,大家可以把缓存新鲜度看作是缓存的保质期(即浏览器可以缓存该资源的时间)后其公式便不难理解。
缓存使用期 = 响应使用期 + 传输延迟时间 + 停留缓存时间
响应使用期
我们先来介绍下响应使用期,响应使用期可以通过以下两种方式进行计算:
- max(0, response_time - date_value)
- age_value
第一种方式中的 response_time(浏览器缓存收到响应的本地时间)是电脑客户端缓存获取到响应的本地时间,而 date_value(响应首部 date 值) 上面已经介绍过是服务器创建报文的时间,两者相减与 0 取最大值。
第二种方式直接获取 age_value (响应首部 age 值),Age 表示推算资源创建经过时间,可以理解为源服务器在多久前创建了响应或在代理服务器中存贮的时长,单位为秒。如下所示:
age:600
以下是 MDN 中的介绍
Age 的值通常接近于 0。表示此对象刚刚从原始服务器获取不久;其他的值则是表示代理服务器当前的系统时间与此应答中的通用头 Date 的值之差。
传输延迟时间
因为 HTTP 的传输是耗时的,所以传输延迟时间是存在的,传输延迟时间可以理解为浏览器缓存发起请求到收到响应的时间差,其计算公式为:
传输延迟时间 = response_time - request_time
response_time 代表浏览器缓存收到响应的本地时间,request_time 代表浏览器缓存发起请求的本地时间,两者相减便得到了传输延迟时间。
停留缓存时间
停留缓存时间表示资源在浏览器上已经缓存的时间,其计算公式为:
停留缓存时间 = now - response_time
now 代表电脑客户端的当前时间,response_time 代表浏览器缓存收到响应的本地时间,两者相减便得到了停留缓存时间。
max-age 仍然受到本地时间影响揭秘
通过上述字段及公式的介绍,最终我们总结出影响强缓存使用期的因素有以下几个:
-
age_value:响应首部 age 值
-
date_value:响应首部 date 值
-
request_time:浏览器缓存发起请求的本地时间
-
response_time:浏览器缓存收到响应的本地时间
-
now:客户端当前时间
需要注意的是以上 request_time、response_time 和 now 取的都是客户端本地时间,而 now 则是修改客户端本地时间直接导致强缓存失效的“罪魁祸首”。
因此一旦修改了电脑客户端本地时间为未来时间,缓存使用期的计算便会受到影响,主要是停留缓存时间会变大,从而导致缓存使用期超出缓存新鲜度范围(强缓存失效)。 这便是 max-age 仍然受到本地时间影响的原因所在。
综上,如果网速正常、用户本地时间正常,强缓存的过期时间主要受到age、 max-age、expires 、date的影响。这几个除了date,在后端均可配置