只靠Expires或HTML meta标签不可靠:Expires依赖时钟同步易失效,meta标签不被主流浏览器支持;必须用响应头中的Cache-Control配合ETag(优于Last-Modified)实现精准、鲁棒的缓存控制。

直接用 Cache-Control 配合 ETag 或 Last-Modified,就能让重复请求不传资源体——这是减少网络传输最有效、最可控的方式。
为什么不能只靠 Expires 或 HTML <meta> 标签
Expires 是 HTTP/1.0 的遗留方案,依赖服务器与客户端时钟严格同步;一旦时间偏差超过几秒,缓存就可能提前失效或误判。而 HTML 中的 <meta http-equiv="Cache-Control" content="max-age=3600"> 根本不被主流浏览器支持——Chrome、Firefox、Safari 都会忽略它。只有响应头里的 Cache-Control 才真正生效。
- 服务端必须通过响应头(不是 HTML 内容)发送缓存指令
-
Expires只能设绝对时间,Cache-Control: max-age=3600用相对秒数,更鲁棒 - CDN 和中间代理通常不解析 HTML meta,只认 HTTP 响应头
Cache-Control 的关键参数怎么选
对静态资源(JS/CSS/图片),优先用 public, max-age=31536000, immutable:一年有效期 + 不可变性声明,让浏览器跳过协商请求。对 HTML 页面本身,建议 no-cache ——不是禁止缓存,而是强制走协商流程,靠 ETag 判断是否真要重传内容。
-
public允许 CDN 和代理缓存;private仅限用户浏览器(如含用户数据的 JSON) -
immutable告诉浏览器:“这个 URL 永远不会变内容”,避免在 F5 刷新时发If-None-Match - 千万别对 HTML 设
max-age过长,否则用户看不到更新(除非改文件名或加 hash)
协商缓存必须配 ETag 而不是只用 Last-Modified
Last-Modified 精度只有秒级,且文件修改时间可能被构建工具重写(比如每次打包都生成新时间戳),导致本该命中的缓存被误判为失效。而 ETag 是服务器基于内容生成的哈希值(如 "abc123"),只要内容不变,ETag 就不变。
立即学习“前端免费学习笔记(深入)”;
- Nginx 默认开启
ETag;Apache 需确认FileETag未被禁用 - 若用构建工具(如 Webpack/Vite),确保输出文件名带 content hash(如
main.a1b2c3.js),再配Cache-Control: public, max-age=31536000,此时甚至可以不用协商缓存 - 分布式部署时,若用弱 ETag(
W/"xxx")且后端节点不共享哈希逻辑,可能造成 ETag 不一致,建议关掉或统一用强 ETag
最容易被忽略的是:缓存策略必须和资源发布方式对齐。比如 HTML 用 no-cache,但 JS 却没加 hash,结果 HTML 更新了,浏览器仍从缓存加载旧 JS——这不是缓存机制的问题,是部署链路没闭环。



















