必须用内容哈希重命名静态资源并配cache-control: immutable,否则url不变导致缓存无法更新;html引用需同步替换,避免404;禁用expires以防时间偏差破坏缓存。

只设 Cache-Control: max-age=31536000 不能提高复用率,反而会让旧资源长期卡在用户本地——URL 不变,浏览器根本不会发新请求,哪怕你服务器上文件早更新了。
必须用内容哈希重命名静态资源
浏览器缓存靠 URL 唯一识别资源。内容变了但 URL 没变,缓存就永远不刷新。
- 构建时把
app.js编译成app.a1b2c3d4.js,CSS 和图片同理 - Webpack 用
[contenthash],Vite 默认开,Rollup 配output.entryFileNames: "[name].[hash].js" - HTML 中引用的路径要同步替换,否则会 404;用 HtmlWebpackPlugin 或构建插件自动注入
- 别手写哈希值,也别用时间戳或版本号——它们不反映内容变化,无法保证缓存有效性
加 immutable 跳过协商缓存
即使用了哈希命名,用户按 F5 刷新时浏览器仍会发 If-None-Match 请求验证,多一次网络往返。
-
Cache-Control: public, max-age=31536000, immutable告诉浏览器:“这个 URL 对应的内容终身不变”,连协商缓存都跳过 - Nginx 配置里漏掉
immutable是常见疏忽:add_header Cache-Control "public, max-age=31536000, immutable"; - 注意:只对哈希命名的资源加
immutable;带查询参数的 URL(如app.js?v=1.2)不适用,它本身就不稳定
别混用 Expires 和 Cache-Control
Expires 依赖客户端系统时间,2026 年如果用户把电脑时间调到 2030 年,缓存当场失效——而你完全没法控制。
- 只要用了
Cache-Control: max-age,就不要配Expires,HTTP/1.1 规范明确说前者优先级更高 - Spring Boot 的
setCachePeriod(31536000)底层只写Cache-Control,是安全的;但手动写响应头时容易误加Expires - CDN 日志里如果看到大量 304,先查是不是
Expires和max-age冲突导致协商逻辑异常
真正卡住复用率的,往往不是没配缓存头,而是哈希没打准、immutable 没生效、或者 HTML 引用的仍是旧文件名——这三处任何一个断掉,整个链路就退回“每次全量下载”状态。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











