一文总结HTTP缓存
缓存是一个很大的话题,本文只是讲述HTTP缓存。
HTTP
浏览器缓存机制
缓存规则解析
浏览器存在一个缓存数据库,用于存储缓存信息。
在客户端第一次请求数据时,此时缓存数据库中没有对应的缓存数据,需要请求服务器,服务器返回后,将数据存储至缓存数据库中。
HTTP缓存有多种规则,根据是否需要重新向服务器发起请求来分类,将其分为两大类(强制缓存,对比缓存)
HTTP 头信息控制缓存
大致分为两种:强缓存和协商缓存。强缓存如果命中缓存不需要和服务器端发生交互,而协商缓存不管是否命中都要和服务器端发生交互,强制缓存的优先级高于协商缓存。
两类缓存规则的不同,强制缓存如果生效,不需要再和服务器发生交互,而对比缓存不管是否生效,都需要与服务端发生交互。
匹配流程:
强缓存
可以理解为无须验证的缓存策略。响应头包括两种字段 HTTP/1.0 Expires和HTTP/1.1 Cache-Control。Cache-Control 比 Expires 优先级更高。
Expires
Expires 指缓存过期的时间。Expires 存在于 。到期时间是由服务端生成的,客户端时间可能跟服务端时间有误差,会导致缓存命中的误差。
Cache-Control
Cache-Control 可以由多个字段组合而成,多个指令以逗号分隔。分客户端和服务端。
客户端可以在HTTP请求中使用的标准 Cache-Control 指令。
Cache-control: max-age=<seconds>
Cache-control: max-stale[=<seconds>]
Cache-control: min-fresh=<seconds>
Cache-control: no-cache
Cache-control: no-store
Cache-control: no-transform
Cache-control: only-if-cached
服务器可以在响应中使用的标准 Cache-Control 指令。
Cache-control: must-revalidate
Cache-control: no-cache
Cache-control: no-store
Cache-control: no-transform
Cache-control: public
Cache-control: private
Cache-control: proxy-revalidate
Cache-control: max-age=<seconds>
Cache-control: s-maxage=<seconds>
cache-control参数讲解
- max-age 指定一个缓存有效时间长度,单位s。后续需要使用这个资源,浏览器不会发出 HTTP 请求,而是直接使用本地缓存的文件
- s-maxage 同 max-age,覆盖 max-age、Expires,但仅适用于共享缓存,在私有缓存中被忽略
- public 响应可以被任何对象(客户端、代理服务器等)缓存
- private 默认值,响应只能被单个用户缓存,非共享,不能被代理服务器缓存
- no-cache 需要使用对比缓存来验证缓存数据
- no-store 禁止缓存,每次请求都要向服务器重新获取数据。强制缓存,对比缓存都将失效
- must-revalidate
- proxy-revalidate
- no-transform
注:
拓展缓存指令不是核心HTTP缓存标准文档的一部分,使用前请注意检查兼容性!
Cache-control: immutable
Cache-control: stale-while-revalidate=<seconds>
Cache-control: stale-if-error=<seconds>
怎样决定一个资源的Cache-Control策略呢?参考定义最佳 Cache-Control 策略
Pragma
存在于HTTP/1.0版本中,只有一种值Pragema:no-cache
, 防止页面被缓存,等价于HTTP/1.1中Cache-Control:no-cache
。
协商缓存
对比缓存,服务端下发的缓存时间到期,并不意味着资源内容发生改变,如果本地资源和服务器上的资源没有差异,实际上没有必要再次请求。客户端和服务器端通过某种验证机制验证当前请求资源是否可以使用缓存。
浏览器第一次请求数据之后会将数据和响应头部的缓存标识存储起来。再次请求时会带上存储的头部字段,服务器端验证是否可用。返回 304 Not Modified,代表资源没有发生改变可以使用缓存的数据,获取新的过期时间。返回 200 则需要重新请求一遍资源并替换旧资源。
Last-modified/If-Modified-Since
Last-modified: 服务器端资源的最后修改时间,响应头部会带上这个标识。第一次请求之后,浏览器记录这个时间,再次请求时,请求头部带上 If-Modified-Since
即为之前记录下的时间。服务器端收到带 If-Modified-Since 的请求后会去和资源的最后修改时间对比。若修改过就返回最新资源,状态码 200,若没有修改过则返回 304。
注意:如果响应头中有 Last-modified 而没有 Expire 或 Cache-Control 时,浏览器会有自己的算法来推算出一个时间缓存该文件多久,不同浏览器得出的时间不一样,所以 Last-modified 要配合 Expires/Cache-Control 使用。
Etag/If-None-Match
Etag,即Entity Tag,由服务器端上生成的一段 hash 字符串,生成规则由服务器决定(比如根据资源的索引节(INode),大小(Size)和最后修改时间(MTime)进行Hash),对应着唯一资源。第一次请求时响应头带上 ETag,随后的请求带上 If-None-Match,服务器检查 ETag,返回 304 或 200。优先级高于Last-modified/If-Modified-Since
last-modified 和 Etag 区别:
- 某些服务器不能精确得到资源的最后修改时间,这样就无法通过最后修改时间判断资源是否更新。
- Last-modified 只能精确到秒。
- 资源的最后修改时间改变,但内容不一定改变,使用 Last-modified 看不出内容没有改变。
- Etag 的精度比 Last-modified 高,属于强验证,要求资源字节级别的一致,优先级高。如果服务器端有提供 ETag 的话,必须先对 ETag 进行 Conditional Request。
浏览器刷新
以Chrome为例,有两类(只需要看加载页面时的第一个请求):
- 正常重新加载
按下刷新按钮(F5)或Ctrl + R
会触发浏览器的正常重新加载normal reload,浏览器会直接认为缓存已经过期(可能缓存还没有过期),带如下请求头:Cache-Control:max-age=0
,此时浏览器会执行一次 Conditional GET。 - 强制重新加载
强制刷新页面(Ctrl+F5)或Ctrl+Shift+R
快捷键触发强制重新加载(Hard Reload),此时包括页面本身在内的所有资源都不会使用缓存。在请求中加上字段:Cache-Control:no-cache
或(和)Pragma:no-cache
。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix