核心思路是通过url变化使浏览器请求新版本资源而非清除缓存;具体包括:①加版本号参数(如?v=2.1.0)并用构建环境变量生成,禁用时间戳;②推荐构建时生成contenthash文件名(如app.a1b2c3d4.js)并配cache-control: immutable;③html需禁用强缓存,设no-cache/must-revalidate;④service worker通过变更缓存名、skipwaiting等实现精准版本控制。

核心思路不是“清除缓存”,而是让浏览器把新版本当作全新资源来请求——靠的是 URL 变化,而非删除磁盘文件。版本号更新的关键,在于让每次发布都生成不可复用的资源路径,并配合合理的缓存头协同生效。
给静态资源加版本号参数(简单直接)
在 HTML 中引用 JS/CSS 时,显式拼接版本号作为查询参数:
-
<script src="app.js?v=2.1.0"></script>或<link rel="stylesheet" href="style.css?v=2.1.0"> - 版本号建议来自构建环境变量(如
NEXT_PUBLIC_APP_VERSION),确保与实际发布版本一致 - 避免用时间戳(如
?t=1723567890),否则所有资源永久不缓存,失去性能优势 - 注意:仅改参数不改文件内容时,浏览器仍可能复用缓存;真正生效依赖服务端返回
200(非304)
构建时生成内容哈希文件名(推荐生产环境)
比手动拼版本号更可靠,由构建工具自动完成:
- Webpack/Vite 等默认支持
[name].[contenthash].js,例如app.a1b2c3d4.js - 文件内容一变,哈希就变,URL 必然不同 → 浏览器无条件发起新请求
- HTML 中的 script/link 标签由构建工具自动更新,无需人工维护
- 搭配 HTTP 响应头
Cache-Control: max-age=31536000, immutable,实现长期强缓存 + 安全不可变
HTML 文件本身要禁用强缓存
HTML 是入口,必须每次检查是否更新,不能被长期缓存:
- 服务端配置响应头:
Cache-Control: no-cache, must-revalidate(触发 ETag/Last-Modified 验证) - 纯静态托管(如 Netlify、Vercel)可通过
_headers或vercel.json统一设置 - 不推荐仅靠
<meta http-equiv="cache-control">,它对 HTTP 缓存控制力弱且不可靠
Service Worker 主动管理带版本的缓存
适合 PWA 或需离线能力的场景,实现精细控制:
- 每次更新 SW 脚本时,必须变更缓存名(如从
static-v2改为static-v3) -
install阶段打开新缓存并预加载新版资源;activate阶段调用caches.keys()清理旧缓存名 -
fetch事件中明确使用caches.match(req, { cacheName: CACHE_NAME }),避免模糊匹配 - 新 SW 需调用
self.skipWaiting()和clients.claim()才能立即接管页面(慎用于生产)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











