有人整理了一份避坑清单 - 91视频,关于缓存设置的说法——看完我沉默了三秒?有新情况我会继续补

经典回顾 0 60

有人整理了一份避坑清单 - 91视频,关于缓存设置的说法——看完我沉默了三秒?有新情况我会继续补

有人整理了一份避坑清单 - 91视频,关于缓存设置的说法——看完我沉默了三秒?有新情况我会继续补

前言 有人把关于“缓存应该怎么设置”的各种说法整理成一份避坑清单,看到后我沉默了三秒——有的建议很实用,有的则容易把人带进误区。把这些断言拆开来看,结合实战经验,把可用的、要避免的和替代做法都罗列出来,方便做站点、CDN或前端性能调优时参考。

总体结论(简短版)

  • 静态资源(版本化后的CSS/JS/图片)可以大量缓存并且用长期 max-age;用文件名指纹做强缓存策略(cache busting)。
  • 动态或用户特定的响应不应被共享缓存(用 private / no-store / no-cache )
  • CDN 与浏览器缓存配合时,要用 s-maxage、stale-while-revalidate 等策略并配合清除/版本化机制。
  • 很多“万能配方”并不万能,需根据资源类型、敏感性与更新节奏细化策略。

常见说法逐条点评(与对策) 1) “所有资源都设置很长的 max-age,能最大化命中率”

  • 对:对静态、版本化资源有效,显著减少请求。
  • 弊端:未指纹化的资源一旦发布错误,用户可能拿到旧版本。对策:对静态资源采用文件名带版本(如 app.abcdef.js),配合 Cache-Control: public, max-age=31536000, immutable。

2) “API 都不要缓存”

  • 实情:并非所有 API 都需要实时性。有些接口(配置、榜单、热门列表)可以有短时缓存;对公共数据可用 CDN 缓存(s-maxage)。
  • 对策:对需要新鲜度较低的数据使用 Cache-Control: public, max-age=60 或 s-maxage=30;对用户敏感或带认证的接口使用 Cache-Control: private, no-store。

3) “no-cache = 不缓存”

  • 说明:no-cache 并不是完全不缓存,而是指缓存前必须向源站验证(如果用 ETag/Last-Modified,可用条件请求)。no-store 才真正表示“不在任何缓存中存储”。
  • 对策:用清晰的指令:需要验证就 no-cache;绝对不存储就 no-store。

4) “ETag 比 Last-Modified 一定更好”

  • 说明:ETag 更精确,但在分布式部署(多台机器)或 CDN 后端克隆时可能不同步导致命中率下降;Last-Modified 更简单,但粒度粗。
  • 对策:如果后端能稳定生成相同 ETag(或使用统一构建产物),可用 ETag;否则用 Last-Modified 或两者结合。

5) “CDN 会自动负责一切”

  • 说明:CDN 很强,但配置有细节:是否缓存带 query string 的 URL、如何处理 Set-Cookie、如何失效(purge)、是否支持缓存标签等都会影响结果。
  • 对策:明确 CDN 行为,使用版本化 + 缓存标签或 API 清除接口,避免依赖即时 purge(会影响延迟和成本)。

推荐配置例子(常见场景)

  • 静态资源(指纹化) Cache-Control: public, max-age=31536000, immutable
  • 图片 / 视频(内容确实不常变) Cache-Control: public, max-age=2592000 (30天)或更长
  • API(可缓存) Cache-Control: public, s-maxage=60, stale-while-revalidate=30
  • 登录/个人数据页面 Cache-Control: private, no-store, no-cache, must-revalidate
  • 敏感表单 / 支付页 Cache-Control: no-store

Nginx 设置示例(思路)

  • 对静态目录添加长期缓存头;
  • 对带 Cookie 的响应避免走 CDN 缓存;
  • 用 add_header Cache-Control … always 来确保头部生效。

常见坑与修复办法

  • 页面更新后用户仍看到旧内容:通常是因为未指纹化并且浏览器/中间缓存未被清除。修复:使用构建产物指纹、或者在发布时使用 CDNs purge+短 TTL 临时策略。
  • 私有数据被缓存到共享缓存:检查响应是否带有 Set-Cookie 或 Authorization,默认应防止共享缓存(Cache-Control: private/no-store)。
  • gzip/压缩混淆缓存:确保 Vary: Accept-Encoding 存在,避免不同压缩版本被误用。
  • CDN 忽略 query string:一些 CDN 把 query string 作为缓存 key 或忽略它,要根据行为调整,推荐用静态文件指纹替代 query string 控制版本。
  • ETag 在多机部署不一致:可以在构建阶段生成统一的哈希作为 ETag,或仅使用 Last-Modified/版本号。

Service Worker 相关

  • 优点:灵活策略(cache-first、network-first、stale-while-revalidate)。
  • 陷阱:错误的 SW 逻辑会导致长期离线化旧资源或阻止更新。建议把 SW 的更新文件本身也指纹化,并在激活流程中明确清理旧缓存。

验证与监控(实用命令/方法)

  • 快速查看响应头:curl -I https://example.com/path
  • 浏览器 DevTools Network 查看是否 200/304、Cache-Control、Expires、Vary 等
  • 用合成测试(WebPageTest/Lighthouse)检查缓存收益
  • 在流量高峰时观察 CDN 命中率、源站带宽和响应时间

隐私与安全注意

  • 切勿把含有身份标识、敏感信息的响应设为 public 或被 CDN 缓存。
  • 登录后页面应确保 Set-Cookie 与 Cache-Control 配合,避免共享缓存中泄露用户内容。
  • 在 HTTPS 环境下,shared proxy 仍可能缓存响应——用 private/no-store 控制。

小结 缓存既是性能利器,也是新手易踩的坑。把资源按“可长期缓存 / 可短期缓存 / 绝对不缓存”分类,并配合版本化、CDN 策略和监控,就能把利得最大化、风险最小化。看完那份避坑清单后,我沉默了三秒——因为好多点确实值得照抄,但更重要的是把这些规则按场景拆开、按骨架实现而不是一句话套用。

有新情况我会继续补。

相关推荐: