浏览器复用css缓存取决于cache-control和etag响应头,而非文件内容是否修改;推荐设置cache-control: public, max-age=31536000,并确保构建工具更新html引用、cdn透传、服务端不覆盖,端到端一致才有效。

浏览器是否复用 CSS 缓存,不取决于你改没改文件内容,而取决于服务器返回的 Cache-Control 和 ETag 响应头——哪怕你重命名了文件但响应头没变,浏览器仍可能加载旧缓存。
Cache-Control 设置必须明确且长期
对静态 CSS 文件,应强制启用强缓存。常见错误是只设 Cache-Control: public 或留空,这等同于无策略;更糟的是设成 no-cache 或 max-age=0,等于主动禁用缓存。
-
Cache-Control: public, max-age=31536000是推荐值(一年),适用于所有未签名、不敏感的 CSS 文件 - 若使用 CDN,确保 CDN 节点也透传并遵守该头,而非覆盖为短时效
- 避免混用
Expires与Cache-Control:当两者共存时,Cache-Control优先级更高;但若仅设Expires,HTTP/2 下可能被忽略
文件名哈希不是缓存开关,而是缓存刷新触发器
给 CSS 加哈希(如 main.a8f3b2d.css)本身不会让浏览器“重新下载”,它只是让浏览器认为这是个新 URL —— 所以只有当 HTML 中引用路径变更时,才真正绕过旧缓存。
- 构建工具(如 Webpack、Vite)需同时完成两件事:生成带内容哈希的文件名 + 更新 HTML 中的
<link href="..."> - 单独改文件内容但不更新 HTML 引用,浏览器仍加载旧哈希文件,且不会感知变化
- 服务端若配置了基于路径的缓存规则(如 Nginx 的
location ~ \.css$),也要确认其未覆盖或忽略哈希路径
协商缓存只在强缓存失效后生效,别指望它提速首次访问
If-None-Match 和 If-Modified-Since 请求头只出现在强缓存过期之后。也就是说,如果 max-age 设为一年,用户一年内根本不会发这些请求——也就谈不上“协商”。
- 协商缓存的价值在于:强缓存过期后,若文件未变,服务器返回
304 Not Modified,省带宽但不省 DNS/TCP/SSL 开销 - 若你频繁发布小修样式,却设了超长
max-age,反而会掩盖真实变更——用户看不到效果,误以为部署失败 -
ETag应基于文件内容生成(而非修改时间),否则文件内容不变但 mtime 变,也会导致误判为变更
真正容易被忽略的是:缓存策略必须端到端一致——从构建输出、CDN 配置、Web 服务器响应头,到 HTML 中的引用路径,任意一环断掉,缓存就形同虚设。尤其在灰度发布或 A/B 测试场景下,不同版本 HTML 指向同一份 CSS 但期望不同样式时,仅靠哈希或版本号根本不够,得配合独立域名或路径隔离。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











