Skip to content

请求报文和相应报文

报文中报头部分使用冒号分隔的键值对组成,称为首部字段。部分首部字段在响应和请求中均有,称为通用首部字段。

强缓存

expires

(响应首部字段)资源有效时间,表示在此事件前资源使用缓存。Expires: Wed, 11 May 2022 03:50:47 GMT

cache-control

(通用首部字段)缓存控制,由以下字段组成

  • max-age 缓存最大时间,是一个相对时间,同时可用于请求,表示希望获得一个max-age 不大于指定值的资源,单位是秒。max-age 会覆盖expires,一般expires和max-age需要同时存在,兼容性设置。
  • s-maxage 表示代理服务器最大缓存时间,公共服务器接受到这个参数后,会直接使用这个,忽略其他expires 和 max-age
  • public/private 表示资源是否能够被缓存服务器缓存, 不过一般缓存服务器不会处理这个字段,照样缓存。
  • no-cache/no store,no-cache在请求中时,表示不使用缓存服务器资源,使用源资源,同时也可以向源资源表示,使用最新资源。在响应中需要使用no-store 才表示真正的不缓存
  • no-cache 不进行强缓存(重要)
  • no-store 不强缓存,也不协商缓存。

协商缓存

Last-Modified 和 If-Modified-Since

Last-Modified 资源最后修改时间,浏览器接收当前资源后,下次在请求头中添加If-Modified-Since 字段。服务器验证是否有效,有效返回304。无效返回200、最新资源和最新的Last-Modified

Last-Modified值实列如下,时间精度到秒Last-Modified: Fri , 14 May 2021 17:23:13 GMT。如果资源是毫秒级别的更新,可能会出现资源不是最新的情况。所以新出现了Etag和If-None-Match

Etag 和 If-None-match

Etag在响应头中返回,用于标志资源的唯一性,资源每次变化时,Etag会重新生成。浏览器下次发送请求通过If-None-match发送。服务器对比处理逻辑同Last-Modified

缓存位置

  • memory cache 内存缓存
  • disk cache

缓存时间如何计算

缓存新鲜度 = max-age || (expires - date) date 表示响应头中的Date字段 缓存使用期 = 响应使用期 + 传输延迟时间 + 停留缓存时间

  • 响应使用期 = max(0, response_time - date_value),然后再和响应头age(秒)max
  • 传输延迟时间 = 响应时间 - 请求时间
  • 停留缓存时间 = now - 响应时间 now表示电脑当前时间。修改电脑时间使缓存失效的关键点。

当缓存使用期大于缓存新鲜度时,强缓存会失效,会启用缓存协商,如果无协商缓存,会重新请求。

启发式缓存

上述可见强缓存新鲜度 = max-age || (expires - date)。如果max-age、expires、date不存在。缓存新鲜度计算规则 max(0, date - Last-Modified ) * 10%

开发模式下的刷新操作

  • 硬性重新加载:不使用本地缓存,同时请求时在请求中添加cache-control: no-cache, 告知服务器和代理服务器不使用缓存。

使用硬性加载没有用的原因是,这两个请求头仅在页面渲染时添加,通过动态脚本添加的资源不会添加这个请求头,还是会走强缓存。

  • 清空缓存并强制加载:清空本地缓存并硬性加载

spa情况下如何配置缓存策略

spa通过加载一个index.html,index.html中再加载相关文件完成界面。这里就有两个地方index.html 和 其他资源。

  • index.html 文件名不会变化,需要使用协商缓存,服务端配置max-age = 0, 但是不能配置cache-control: no-store

  • 其余资源,设置强缓存。根据文件内容变化文件名,保证每次引用都是新的,也不会走缓存。

webpack 如何使用强缓存

  • hash 项目级别的hash
  • chunkhash 根据 入口文件相关的依赖进行hash
  • contenthash,根据每个文件内容变化的hash

nginx 如何配置缓存

  • 针对静态资源设置