HTTP 缓存完全指南:让网站快起来的那些事

缓存链路
当你访问一个网站时,请求不只是直接从浏览器到服务器。中间可能经过多个层:
浏览器 → 代理/CDN缓存 → 源服务器
浏览器有自己的私有缓存,中间的CDN和代理服务器有共享缓存。理解这个链路是配置缓存的第一步。
新鲜度 vs 过期
缓存的核心判断逻辑很简单:这个响应还是”新鲜”的吗?
什么决定新鲜度
服务器通过 Cache-Control 告诉缓存能存多久:
Cache-Control: max-age=3600
这意味着”这个内容能用1小时”。
优先级顺序:
1. Cache-Control: max-age=<秒数> — 最优先
2. Expires 头部 — 旧方案,指定具体过期时间
3. 启发式过期 — 没有明确指示时,根据 Last-Modified 猜一个
对于共享缓存,s-maxage 会覆盖其他所有设置。
年龄怎么算
缓存的年龄不是从你下载开始算,而是从服务器生成或最后一次验证开始算。中间代理还会加上 Age 头部的时间。
过期后的验证
内容过期不一定要扔掉。可以用条件请求验证:
If-Modified-Since: 2025-01-10
If-None-Match: "abc123"
服务器会返回:
– 304 Not Modified — 内容没变,继续用缓存
– 200 OK + 新内容 — 有更新
版本标识用 ETag(通常是内容的哈希)比 Last-Modified 更可靠。
常用 Cache-Control 指令
响应指令
| 指令 | 作用 |
|---|---|
max-age=<秒> |
新鲜存活时间 |
must-revalidate |
过期必须验证,服务器错误时不许用旧内容 |
no-cache |
每次都要验证,等同于 max-age=0, must-revalidate |
no-store |
完全不许缓存 |
private |
只能浏览器缓存,CDN别碰 |
public |
允许共享缓存(包括带 Authorization 的请求) |
s-maxage=<秒> |
只影响共享缓存的新鲜时间 |
immutable |
内容不会变,刷新页面时别来验证 |
实用组合
# 静态资源(长期不变)
Cache-Control: public, max-age=31536000, immutable
# HTML 页面(需要更新但可缓存)
Cache-Control: public, max-age=0, must-revalidate
# API 响应(不缓存)
Cache-Control: no-store
# 用户特定内容
Cache-Control: private, max-age=600
浏览器的刷新机制
用户刷新页面时,浏览器行为不一样:
- 软刷新 (Cmd+R): 只验证主文档,子资源按缓存规则来
- 硬刷新 (Cmd+Shift+R): 所有资源都跳过缓存,重新下载
历史上软刷新会验证所有资源,但大约2015年后,浏览器改成了只验证主文档。这就是 immutable 指令现在有点尴尬的原因 — 新的刷新策略已经解决了它想解决的问题。
认证请求的缓存
带 Authorization 头的请求默认不能被共享缓存存储。除非明确允许:
publics-maxagemust-revalidate
这三个指令会让共享缓存存储认证响应。用的时候要小心。
容易踩的坑
no-cache 不是不缓存
no-cache 的意思是”用之前先验证”,不是”完全别存”。想要完全不缓存,用 no-store。
immutable 支持度问题
Chrome 不太支持,Safari 和 Firefox 支持。但由于现代浏览器的刷新策略变化,这个指令实际意义不大。
刷新行为不一致
Safari 在硬刷新后,后续软刷新仍会带 no-cache。这可能是个 bug,但不影响正常使用。
304 响应也会更新头部
即使返回 304,服务器会把新的缓存头部带回来。缓存的”新鲜度计时器”会重置。
实践建议
- 静态资源用长缓存: CSS、JS、图片用
max-age=31536000, immutable - 文件名加哈希:
main.abc123.js这样改了内容文件名也变了 - HTML 用短缓存:
max-age=0, must-revalidate确保能更新 - API 响应谨慎缓存: 默认
no-store,确实能缓存才设置其他值 - 不要只依赖
Expires: 旧方案,有max-age就不用它
小结
HTTP 缓存不复杂,但细节多。记住核心逻辑:
- 服务器说能存多久,缓存就听多久
- 过期了先验证再决定要不要重新下载
- 不同场景用不同指令组合
- 浏览器刷新行为不是你想的那样
大多数网站只需要两套配置:静态资源长期缓存,HTML 始终验证。足够了。







AI周刊:大模型、智能体与产业动态追踪
程序员数学扫盲课
冲浪推荐:AI工具与技术精选导航
Claude Code 全体系指南:AI 编程智能体实战
最新评论
Flash版本的响应速度确实提升明显,但我在使用中发现对中文的理解偶尔会出现一些奇怪的错误,不知道是不是普遍现象?
遇到过类似问题,最后发现是网络环境的问题。建议加一个超时重试机制的示例代码。
谢谢分享,我是通过ChatGPT的索引找到这里来的。
十年打磨一个游戏确实罕见,这种专注度在快节奏的游戏行业很难得。从Braid到The Witness,每作都是精品。
快捷键冲突是个很实际的问题,我自己也被这个问题困扰过。最后通过自定义快捷键组合解决了。
会议摘要这个功能很实用,特别是对经常需要参加长会议的人。不过三次免费使用确实有点少了。
硕士背景转AI基础设施,这个路径其实挺常见的。建议多关注底层系统知识,而不只是模型应用层面。
配置虽然简单,但建议补充一下认证和加密的注意事项,避免被中间人攻击。