缓存控制

HTTP


通常浏览器缓存策略分为两种:强缓存协商缓存,并且缓存策略都是通过设置 HTTP Header 来实现的

# 强缓存

强缓存可以通过设置两种 HTTP Header 实现:

  • ExpiresCache-Control
  • 强缓存表示在缓存期间不需要请求status: 200

# Expires

该字段的值是一个绝对时间

Expires: Wed, 22 Oct 2018 08:41:00 GMT
1

Expires 是 HTTP/1.0 的产物,表示资源会在 Wed, 22 Oct 2018 08:41:00 GMT 后过期,需要再次请求。并且 Expires 受限于本地时间,如果修改了本地时间,可能会造成缓存失效

# Cache-control

该字段的值是一个相对时间,而且在请求头与响应头中都可设置

Cache-control: max-age=30
1
  • Cache-Control 出现于 HTTP/1.1,优先级高于 Expires 。该属性值表示资源会在 30 秒后过期,需要再次请求。
  • Cache-Control 可以在请求头或者响应头中设置,并且可以组合使用多种指令

在 HTTP/1.1 中,Cache-Control 是最重要的规则,主要用于控制网页缓存,主要取值为:

# 可缓存性相关

  • public:所有内容都将被缓存(客户端和代理服务器都可缓存)
  • private:所有内容只有客户端可以缓存,Cache-Control 的默认取值
  • no-cache:表示客户端可以缓存资源,但每次使用缓存资源前都必须重新验证其有效性
  • no-store:所有内容都不会被缓存,即不使用强制缓存,也不使用协商缓存

# 到期时间相关

  • max-age=xxx (xxx is numeric):缓存内容将在 xxx 秒后失效
  • s-maxage=xxx: 代理缓存的有效时间
  • max-stale=xxx: 表明客户端愿意接收一个已经过期的资源,只要代理缓存过期时间不超过 xxx 秒
  • min-fresh=xxx: 表明客户端可以接受在代理缓存在到期前 xxx 秒的缓存

# 重新验证和重新加载相关

  • must-revalidate:一旦资源过期(比如已经超过 max-age),在成功向原始服务器验证之前,缓存不能用该资源响应后续请求。
  • proxy-revalidate:与 must-revalidate 作用相同,但它仅适用于共享缓存(例如代理),并被私有缓存忽略。

# 其他

  • only-if-cached:表明客户端只接受已缓存的响应,并且不要向原始服务器检查是否有更新的拷贝。

Cache-Control 的值是可以混合使用的,比如:

Cache-Control: private, max-age=0, no-cache
1

当混合使用的时候它们的优先级如下图所示:

# 协商缓存

如果强缓存不可用,就需要通过协商缓存,向服务器发起请求验证资源是否有更新。协商缓存可以通过设置两种 HTTP Header 实现:Last-ModifiedETag 当浏览器发起请求验证资源时,如果资源没有做改变,那么服务端就会返回 304 状态码,且不会返回数据体,并更新浏览器缓存有效期;否则,返回 200,并返回文件内容,根据缓存信息设置缓存。

# Last-Modified 和 If-Modified-Since

Last-Modified 表示资源的最后修改日期,If-Modified-Since 会将 Last-Modified 的值发送给服务器,询问服务器在该日期后资源是否有更新,有更新的话就会将新的资源发送回来,否则返回 304 状态码。

但是 Last-Modified 存在一些弊端:

  • 如果本地打开缓存文件,即使没有对文件进行修改,但还是会造成 Last-Modified 被修改,服务端不能命中缓存导致发送相同的资源
  • 因为 Last-Modified 只能以秒计时,如果在不可感知的时间内修改完成文件,那么服务端会认为资源还是命中了,不会返回正确的资源因为以上这些弊端,所以在 HTTP / 1.1 出现了 ETag

# ETag 与 If-None-Match

ETag 类似于文件指纹,If-None-Match 会将当前 ETag 发送给服务器,询问该资源 ETag 是否变动,有变动的话就将新的资源发送回来。并且 ETag 优先级比 Last-Modified 高

# 如果什么缓存策略都没设置,那么浏览器会怎么处理?

对于这种情况,浏览器会采用一个启发式的算法,通常会取响应头中的 Date 减去 Last-Modified 值的 10% 作为缓存时间。

Last Updated: 10/21/2024, 4:15:17 PM