Cache-Control响应头比meta标签更可靠,因现代浏览器完全忽略,仅认服务端返回的HTTP响应头;HTML应设短缓存或协商缓存,静态资源才宜长期强缓存。

Cache-Control 响应头比 更可靠
直接在 HTML 里用 是无效的。浏览器只认 HTTP 响应头里的 Cache-Control, 标签对 HTML 本身不生效——它最多影响子资源(如内联脚本加载的 JS),但不可靠、不被主流浏览器保证。
真正起作用的方式是让服务器返回正确的响应头:
- 静态资源(CSS/JS/图片):设置
Cache-Control: public, max-age=31536000, immutable - HTML 文件:设为短缓存或禁用强缓存,例如
Cache-Control: no-cache, must-revalidate或max-age=300 - 若用 Nginx,加
expires 1y;配合add_header Cache-Control "public, immutable";到对应 location 块 - 若用 Apache,用
ExpiresByType指令,但注意text/html类型必须单独设为短周期(如"access plus 5 minutes")
HTML 文件不该长期强缓存
把 index.html 缓存一整年看似省请求,实则埋雷:只要 JS/CSS 文件名没带哈希,HTML 里引用的仍是旧路径,用户刷新后看到的还是老代码。更糟的是,某些 CDN 会忽略 HTML 的 Cache-Control,按默认策略缓存数小时甚至数天,导致灰度发布失败。
正确做法是让 HTML 走协商缓存,配合服务端生成的 ETag 或 Last-Modified:
- 每次构建时在 HTML 中注入唯一构建时间戳或哈希,比如
,再由后端读取并设为ETag - 确保服务器对
index.html不返回immutable——这个指令意味着“永不变更”,和 HTML 的语义冲突 - 避免在 HTML 中硬编码
Cache-Control值,它无法覆盖响应头,反而造成误导
prefetch 只对稳定路径有效,别乱用
rel="prefetch" 看似能预加载下一页,但实际生效条件极苛刻:它只缓存原始字节流,且仅当跳转 URL 完全匹配(包括路径、参数、hash)才复用。一旦 URL 含 ?id=123 或 #section2,就彻底失效。
真实可用的场景非常有限:
- 预加载下一跳的 JS chunk,路径形如
/static/js/main.a1b2c3.js(带内容哈希) - 预加载关键 WebP 图片,大小 ≤ 100KB,路径固定无参数
- 必须写在
中,位于和之后、首个之前 - Chrome DevTools Network 面板中 Priority 必须显示为
Low,否则说明漏了as属性(如as="script")
CDN 和浏览器缓存策略要分层设计
CDN 缓存和浏览器缓存不是二选一,而是叠加关系。如果 CDN 返回的响应头里 Cache-Control: public, max-age=86400,而浏览器本地又存着一个 max-age=300 的副本,最终以更短的那个为准(即 5 分钟)。所以 CDN 策略不能盲目拉长。
典型分层建议:
- CDN 层:对
.js/.css/.png等资源设max-age=31536000,但 HTML 设为max-age=60并开启stale-while-revalidate - 浏览器层:依赖服务端响应头,不信任 HTML 内的
;用curl -I https://yoursite.com/index.html实时验证头部是否正确 - 开发阶段用
chrome://cache/(已弃用)或 DevTools Application → Cache Storage 查看是否意外启用了 AppCache / Service Worker 干扰了预期行为
最易被忽略的一点:HTML 文件本身永远不该成为缓存优化的重点对象——它的体积小、变动频繁,真正该长期缓存的是带哈希的静态资源。把精力放在构建流程生成稳定文件名、服务端精确控制响应头、CDN 分路径配置上,比折腾 HTML 的 meta 标签实在得多。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











