server {
listen 80;
server_name your-domain.com;
root /www/wwwroot/your-project;
index index.html;
location / {
# SPA 路由处理
try_files $uri $uri/ /index.html;
}
# ====== JS/CSS 文件:每次重新加载 ======
location ~* \.(js|css)$ {
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
add_header Expires "0";
}
# ====== 图片/字体:可以缓存 ======
location ~* \.(png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 30d;
add_header Cache-Control "public, max-age=2592000";
}
# ====== HTML:永远最新 ======
location ~* \.(htm|html)$ {
add_header Cache-Control "no-cache, no-store, must-revalidate";
}
}
配置说明
文件类型
缓存策略
说明
JS/CSS
不缓存
每次请求最新代码
图片
缓存30天
不常变化,可以缓存
HTML
不缓存
每次加载最新页面
if ($request_uri ~* "/index\.html$") { // 生效的缓存配置
add_header Cache-Control "no-cache, no-store, must-revalidate";
expires off;
}
只要访问的网址最后是 /index.html,就强制浏览器:永远不要缓存,每次都必须去服务器拿最新的!
if ($request_uri ~* "/index\.html$") {
如果用户访问的网址最后是以 /index.html 结尾的,就执行下面的规则。
-
~*= 不区分大小写 -
$= 以 xxx 结尾add_header Cache-Control "no-cache, no-store, must-revalidate";
告诉浏览器 3 件事:
-
no-cache:不许直接用缓存,必须去服务器问一下有没有更新
-
no-store:根本就不许把这个页面保存到本地
-
must-revalidate:用之前必须校验,过期了绝对不能用
expires off;
关闭自动过期时间,不设置缓存有效期 = 不缓存。
最通俗的比喻(你马上懂)
index.html 就像是一张 “随时会变” 的公告。
- 不缓存 = 你每次看公告,必须跑去公告栏看最新的
- 不许存本地 = 你不能把公告拍下来自己存着看旧的
- 必须校验 = 旧的直接作废,只看最新的
为什么要这么配?(前端 Vue/React 项目必用)
因为你们是 Vue 哈希路由项目(就是你那个 /#/xxx):
index.html是入口文件- 一旦发布新版本,必须让用户加载最新的
- 如果浏览器缓存了旧的 index.html → 页面白屏、不更新、跳转异常
所以这段配置就是:
让 index.html 永远不缓存,每次都拿最新!
最终极简总结
访问 index.html → 不缓存、不保存、必须拿最新!
保证用户永远看到最新版前端页面!
更好的方案:加上版本号
除了 Nginx 配置,推荐在打包时自动加 hash:
打包后的文件名:
js/app.abc123.js → 有hash,文件名变了 = 重新加载
css/style.abc123.css
这样即使 Nginx 缓存了,文件名不同也会重新加载。
方案
优点
缺点
方案1:Nginx配置
简单,一次配置
所有用户都重新加载
方案2:加hash文件名
更精准,用户无感知
需要重新打包
推荐两个一起用(加hash + Nginx配置),双重保障。
Vue CLI / Vite 默认:只有生产环境(npm run build)会自动给 JS/CSS 加 hash,
测试环境(npm run serve/dev)不会加!
你要的是:
不管测试环境打包、还是生产环境打包,输出的文件都自动带 hash!
我下面直接告诉你 怎么配置、改哪里、立刻生效。
一、默认规则(你现在的情况)
Vue CLI(vue.config.js)
- 开发环境 serve:文件没有 hash(main.js、app.css)
- 生产环境 build:文件自动带 hash(chunk-xxx.hash.js)
Vite
- 开发 dev:无 hash
- 生产 build:自动带 hash
二、你要的效果:
**测试环境打包(test/build) + 生产环境打包(prod/build)
→ 所有 JS/CSS 全部自动加 hash!**
我给你 最标准、最稳定 的配置👇
三、Vue CLI 配置(vue.config.js)
目标:不管什么环境,只要打包(build)就加 hash
// vue.config.js
module.exports = {
filenameHashing: true, // ✅ 这个就是全局开启 hash(默认 true,但只对生产生效)
// 👇 重点:强制 测试环境/生产环境 都开启 hash
chainWebpack: (config) => {
// 开发环境也强制开启 hash
config.output.filename("js/[name].[hash:8].js");
config.output.chunkFilename("js/[name].[hash:8].js");
// CSS 也强制加 hash
config.plugin("extract-css").tap((options) => {
options[0].filename = "css/[name].[hash:8].css";
options[0].chunkFilename = "css/[name].[hash:8].css";
return options;
});
},
};
作用:
不管是测试、预发、生产,只要执行 npm run build 就一定带 hash!
四、Vite 配置(vite.config.js)
export default defineConfig({
build: {
rollupOptions: {
output: {
entryFileNames: "js/[name]-[hash:8].js",
chunkFileNames: "js/[name]-[hash:8].js",
assetFileNames: "assets/[name]-[hash:8].[ext]",
},
},
},
});
作用:
所有环境打包,JS/CSS/ 图片 全部自动带 8 位 hash!
五、最关键的一句(你必须知道)
filenameHashing: true
这个配置 默认只对生产环境生效
测试环境默认 不生效
所以你必须像我上面那样
手动配置 output 文件名格式
才能让 所有环境打包都带 hash
六、你最终想要的效果我帮你总结
- Vue 项目默认:生产打包才有 hash
- 测试环境默认没有 hash
- 你想:测试 + 生产 都带 hash
- 必须在 vue.config.js/vite.config.js 强制配置文件名
七、我给你最终最稳的配置(复制即用)
Vue CLI 最终版(100% 满足你)
module.exports = {
publicPath: "./",
filenameHashing: true,
chainWebpack: (config) => {
// 强制所有环境打包都带 hash
config.output.filename("js/[name].[hash:8].js");
config.output.chunkFilename("js/[name].[hash:8].js");
config.plugin("extract-css").tap((opts) => {
opts[0].filename = "css/[name].[hash:8].css";
opts[0].chunkFilename = "css/[name].[hash:8].css";
return opts;
});
},
};
八、最简单的验证方式
打包后看 dist 目录:
- 正确:
app.abc123.js - 错误:
app.js
只要出现 xxx.hash.js 就成功!
===