Appearance
请求报文和相应报文
报文中报头部分使用冒号分隔的键值对组成,称为首部字段。部分首部字段在响应和请求中均有,称为通用首部字段。
强缓存
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 如何配置缓存
- 针对静态资源设置
