外观
HTTP 缓存
- 状态:未准备
- 适用方向:共用
- 最近复习:待填写
- 下次复习:待安排
一句话回答
缓存先按新鲜度决定能否直接复用,需要验证时用 ETag 或 Last-Modified 向服务端确认;未变化可返回 304 并复用本地响应体,策略要兼顾更新和隐私。
原理解释
强缓存与协商缓存
中文面试中常把无需验证的直接复用称为强缓存,把条件请求验证称为协商缓存。浏览器不是每次都先请求服务器;已有可用且新鲜的缓存可直接使用。缓存过期也不一定立即删除,而可能保留用于验证。
常见响应头
Cache-Control: max-age=3600:允许在新鲜期内复用,年龄还需结合 Date、Age 等计算。no-cache:可以存储,但再次复用前必须验证;不是“不缓存”。no-store:要求不存储该响应,适合不应落入缓存的敏感内容。private:只允许私有缓存存储;public可允许共享缓存。ETag配合If-None-Match,Last-Modified配合If-Modified-Since;两者同时存在时前者有优先权。Vary指出哪些请求头参与缓存匹配,例如按内容编码区分响应,避免错误复用。
http
GET /app.js HTTP/1.1
If-None-Match: "build-a"
HTTP/1.1 304 Not Modified
ETag: "build-a"
Cache-Control: max-age=3600304 是对条件请求的响应,仍发生网络往返,通常无响应体;DevTools 的 memory/disk cache 标记与 304 不是一回事。
场景与边界
内容哈希文件名可配长新鲜期与 immutable,内容变化时更换 URL;HTML 入口通常采用较短新鲜期或每次验证,避免长期引用旧资源。涉及用户身份的数据需明确私有性和存储策略,不能统一 public。Next.js 数据缓存、Service Worker 和 HTTP 缓存是不同层,排查时先识别来源。
项目中的应用
参考 Blog 构建与数据获取,区分贡献数据再验证与浏览器资源缓存。部署响应头需在真实环境检查,不能从框架配置推断所有 CDN 和浏览器行为。
常见追问
- 为什么有 ETag 还配 max-age? 前者用于验证,后者决定何时需要验证,职责不同。
- Expires 与 max-age 谁优先? 支持两者时 Cache-Control 的 max-age 优先;Expires 是绝对时间。
- 为什么发布后还看到旧页面? 排查 HTML、资源 URL、CDN、Service Worker 和框架数据缓存,不能只让用户反复强刷。