强制缓存与协商缓存
强制缓存
强制缓存是浏览器在请求资源时首先检查的缓存机制。
工作原理
- 浏览器发起请求时,首先检查本地缓存
- 如果缓存存在且未过期,直接使用缓存资源
- 如果缓存不存在或已过期,才向服务器发起请求
控制字段
强制缓存由两个主要的HTTP头部控制:
Expires
- HTTP/1.0的缓存控制字段
- 值为一个绝对时间(如
Expires: Wed, 21 Oct 2025 07:28:00 GMT
) - 缺点:依赖客户端本地时间,如果用户修改了系统时间,可能导致缓存失效
Cache-Control
HTTP/1.1引入的更强大的缓存控制字段
常用指令:
max-age=
:设置缓存的最大生命周期(秒)no-cache
:不使用强制缓存,直接进入协商缓存no-store
:完全不使用任何缓存public
:响应可以被任何中间节点缓存private
:响应只能被浏览器缓存
示例:
Cache-Control: max-age=31536000
优先级:当Cache-Control
和Expires
同时存在时,Cache-Control
的优先级更高。
强制缓存的三种情况
- 缓存不存在:直接向服务器发起请求(如同第一次请求)
- 缓存存在但已过期:强制缓存失效,进入协商缓存阶段
- 缓存存在且未过期:直接使用缓存,状态码200,但显示
from cache
协商缓存
当强制缓存失效时,浏览器会进入协商缓存阶段。
工作原理
- 浏览器携带缓存标识向服务器发起请求
- 服务器根据标识判断资源是否变化
- 如果未变化,返回
304 Not Modified
,浏览器使用本地缓存 - 如果已变化,返回200和新资源
控制字段
协商缓存有两组控制字段:
Last-Modified / If-Modified-Since
- 服务器在首次响应时返回
Last-Modified
头部,表示资源最后修改时间 - 浏览器再次请求时,在
If-Modified-Since
头部带上这个时间 - 服务器比较当前资源修改时间和
If-Modified-Since
值 - 缺点:精度只到秒级,可能因文件内容未变但修改时间变化导致不必要的请求
- 服务器在首次响应时返回
ETag / If-None-Match
- 服务器在首次响应时返回
ETag
头部,是资源的唯一标识符(通常是内容的哈希值) - 浏览器再次请求时,在
If-None-Match
头部带上这个ETag值 - 服务器比较当前资源ETag和
If-None-Match
值 - 更精确,能感知内容变化
- 服务器在首次响应时返回
优先级:当ETag
和Last-Modified
同时存在时,ETag
的优先级更高。
协商缓存的两种情况
- 缓存有效:返回
304 Not Modified
,浏览器使用本地缓存 - 缓存无效:返回200和新资源
缓存流程总结
浏览器发起请求时,先检查强制缓存
- 如果缓存有效且未过期,直接使用缓存
- 如果缓存不存在或已过期,进入协商缓存阶段
协商缓存阶段:
- 浏览器发送请求,携带
If-None-Match
(ETag)和/或If-Modified-Since
(Last-Modified) - 服务器验证资源是否变化
- 未变化:返回304,浏览器使用缓存
- 已变化:返回200和新资源
- 浏览器发送请求,携带
新资源会被浏览器缓存,并更新缓存标识
实际应用建议
- 对于静态资源(如JS、CSS、图片):设置较长的
max-age
(如1年),并使用内容哈希作为文件名或查询参数,这样可以在内容变化时自动失效缓存 - 对于频繁变化的资源:使用
no-cache
或较短的max-age
,依赖协商缓存 - 对于敏感数据:使用
no-store
确保不缓存
通过合理配置缓存策略,可以显著提高网站性能,减少服务器负载,提升用户体验。