只设max-age不够,因url不变时浏览器不会发起新请求,必须配合内容哈希命名(如app.a1b2c3.js)确保url随内容变化;再加immutable跳过协商缓存,public允许多级缓存,提升cdn命中率。

直接用 Cache-Control 配合文件哈希命名,就能让浏览器长期复用 CSS/JS/图片,彻底避免重复请求。
为什么只设 max-age 不够用
单纯给静态资源返回 Cache-Control: max-age=31536000(1年),看似能缓存很久,但一旦文件内容更新,用户仍会拿到旧版本——因为浏览器只看 URL 是否命中缓存,而 URL 没变,它就不会发新请求。
必须配合构建时生成带内容哈希的文件名,例如把 app.js 构建成 app.a1b2c3d4.js。这样每次内容变化,URL 就不同,浏览器自然走全新请求+全新缓存流程。
-
immutable要加上:告诉浏览器“这个 URL 对应的内容永远不会变”,可跳过协商缓存阶段,连ETag或Last-Modified都不用发 - 避免混用
Expires:它依赖客户端本地时间,2026年如果用户手动调快系统时间,缓存就可能提前失效 - CDN 场景下优先用
public, max-age=31536000, immutable,别用private,否则 CDN 不会缓存
public 和 private 到底该选哪个
绝大多数静态资源(.css、.js、.png)都该用 public。它允许中间节点(如 CDN、公司代理)也缓存,大幅提升边缘命中率;而 private 仅限浏览器本地缓存,对部署在 CDN 后面的站点等于浪费了缓存层级。
唯一该用 private 的情况是:某个 JS 文件里硬编码了用户 ID 或 token(极不推荐),且该文件确实不能被任何中间节点看到。
- 判断依据很简单:这个文件是否对所有用户都一样?是 → 用
public - Spring Boot 中配置示例:
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/").setCachePeriod(31536000),底层会自动加Cache-Control: public, max-age=31536000 - Nginx 配置中别漏掉
add_header Cache-Control "public, max-age=31536000, immutable";,否则默认无缓存头
刷新行为如何影响缓存判断
用户按 F5 刷新时,浏览器会跳过强缓存但保留协商缓存逻辑;而地址栏回车或点击链接,才完整走 Cache-Control 判断。这意味着:即使你配了 1 年缓存,用户 F5 后仍可能触发一次 304 请求——这不是 bug,是规范行为。
真正要警惕的是开发阶段的「热更新干扰」:Webpack Dev Server 默认禁用缓存(Cache-Control: no-store),但若你手动加了缓存头又没清掉浏览器磁盘缓存,就可能出现「改了代码却看不到效果」的情况。
- 排查方法:打开 DevTools → Network → 找到该资源 → 看 Response Headers 里有没有
Cache-Control,值是否符合预期 - 本地验证技巧:先正常访问一次,再断网重刷,如果资源还能加载,说明强缓存生效了
- 不要依赖
localStorage或Service Worker去覆盖 HTTP 缓存逻辑,它们属于不同层级,强行混合容易导致状态错乱
最关键的落地点其实就两个:构建时生成带哈希的文件名 + 响应头写死 public, max-age=31536000, immutable。其余都是围绕这两件事查漏补缺。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











