因为移动端WebView(尤其是微信X5内核)几乎忽略<meta http-equiv>缓存标签,其缓存行为由HTTP响应头真正控制,且<meta>仅对HTML首次加载生效,无法影响JS/CSS等后续资源请求。

为什么加标签在移动端H5里常常失效
因为移动端 WebView(尤其是微信内置浏览器、QQ 浏览器、部分安卓系统 WebView)对 <meta http-equiv> 的支持极弱,甚至完全忽略。你写上 <meta http-equiv="Cache-Control" content="no-cache">,它可能照常缓存 index.html,连带里面引用的 js 和 css 一起锁死。这不是 bug,是规范实现差异——HTTP 响应头才真正起效,<meta> 只是 HTML 层面的“建议”,且仅对首次加载的 HTML 生效,对后续资源请求无效。
- 微信 iOS 端几乎无视所有
<meta>缓存控制 - Android 微信、QQ 浏览器多数只认
Expires: 0,但前提是服务器真返回了这个响应头 -
index.html被缓存后,里面写的static/js/app.js就永远指向旧版本,哪怕你改了 JS 内容
必须改 webpack 输出文件名,不能只靠时间戳拼接
很多教程教你在 vue.config.js 里写 filename: `app-${Date.now()}.js`,这看似合理,实则危险:构建时 Date.now() 是构建时刻的时间戳,同一构建产物里所有 chunk 共享同一个时间戳;如果构建后多次部署(比如灰度发布、CDN 多节点同步延迟),不同机器上生成的文件名可能重复,导致 CDN 缓存未刷新却以为已更新。
- ✅ 正确做法:用
contenthash(基于文件内容生成哈希),确保内容变、文件名必变 - ❌ 错误写法:
filename: '[name].js?${Date.now()}'—— query 参数对 CDN 缓存不敏感,且无法触发浏览器强制重载 - ⚠️ 注意:uni-app 默认开启
filenameHashing: true,但需确认manifest.json中"h5": {"optimization": {"chunkSize": 1024}}等配置没意外关闭它
示例有效配置:
module.exports = {
filenameHashing: true,
configureWebpack: {
output: {
filename: 'static/js/[name].[contenthash:8].js',
chunkFilename: 'static/js/[name].[contenthash:8].js'
}
}
}
publicPath 配置错误会直接导致白屏
当 H5 部署到 CDN 时,publicPath 决定所有静态资源的根路径。如果填错,浏览器会去请求一个根本不存在的 URL,比如 https://cdn.example.com/static/js/app.abc123.js 返回 404,整个 JS 加载失败,页面白屏——此时控制台 Network 标签页一眼可见大量 404,但开发者常误以为是缓存问题。
- 必须以
/开头或完整 HTTPS URL 结尾,例如:"https://cdn.example.com/h5/"或"/h5/" - 务必与实际 CDN 目录结构一致;若 CDN 绑定的是
https://cdn.example.com,而你填了"//cdn.example.com/h5/",某些环境会因协议缺失挂掉 - 检查
manifest.json中"h5": {"publicPath": "..."},该字段优先级高于vue.config.js的publicPath
CDN 缓存没刷干净,比本地缓存更难察觉
用户白屏,不是因为手机缓存,而是 CDN 节点还在吐旧版 index.html。这个 HTML 文件一旦被 CDN 缓存,它里面引用的 JS/CSS 地址就固定了,哪怕你把新 JS 上传上去,老 HTML 还在拉旧地址。
- 每次发布后,必须主动刷新 CDN 缓存,重点是
index.html和static/下所有文件(通配符/index.html和/static/*) - 不要依赖 “缓存过期时间” —— CDN 服务商可能有最长缓存兜底策略(如 24 小时),必须手动 purge
- 上线前用 curl 或浏览器隐身模式直连 CDN 域名,检查返回的
index.html是否含最新contenthash文件名
最稳妥的做法:在 index.html 构建时注入唯一构建标识(如 Git commit hash),再配合 CDN 刷新,才能确保端到端链路可控。


















