快速修复
# 一键:发布顺序修正——先上资源、后切入口,旧资源保留至少一个发布周期
# 1) 先把新版本 dist/ 全部上传(含新 hash 资源) 2) 最后再上传/切换 index.html
发布脚本里把 index.html 的覆盖放到最后一步,并且上传时保留旧资源目录。
你会遇到什么
发布新版本后,部分用户白屏,刷新又偶尔恢复;控制台报 ChunkLoadError: Loading chunk N failed;动态 import 请求的带 hash 资源返回 404。你自己访问却是好的——因为你的缓存是新的。
本文路径:快速修复(30 秒一段命令)→ 一步步排查(可跳读)→ 原理与变体(症状/原因/证据)。赶时间直接跳到「快速修复」。
为什么会这样
版本错位:浏览器缓存的旧入口 HTML 仍引用旧版本 hash chunk,而服务器新发布已经删掉了旧资源。用户触发动态 import 时,旧 chunk 404 → 模块加载失败 → 整页白屏。
| 角色 | 状态 |
|---|---|
| 用户浏览器 | 缓存着旧版入口 HTML,指向旧 hash 资源 |
| 服务器 | 已部署新版本,旧资源已删除 |
| 结果 | 旧 chunk 404 → ChunkLoadError → 白屏 |
Vite 构建的 chunk 文件名带内容 hash(实测:feature-DP5yDwy7.js → feature-PcJGFbac.js),版本一变 hash 就变,新旧 HTML 引用的资源完全不同。
Vite 构建产物是「入口 HTML + 带内容 hash 的 chunk」:hash 由文件内容算出,内容变 hash 就变。浏览器先拿到入口 HTML,运行时再按 HTML 里的引用去加载 chunk——这是两步取用,中间隔着一段时间,而这段时间里服务器可能已经发布新版本并删除了旧 chunk。
用户浏览器缓存的旧 HTML 指向旧 hash,服务器已没有该资源 → 动态 import 404 → ChunkLoadError。
确定性推论:这不是代码 bug,是「客户端引用集」与「服务器资源集」的版本错位;修法三选一——部署时保留旧 chunk(不删 dist 旧文件/用带版本前缀的目录)、让入口 HTML 不缓存(Cache-Control: no-cache,chunk 仍可长缓存)、或升级时全量刷新(发布后提示刷新/自动 reload)。
判断依据:Network 面板里失败请求的 URL 带旧 hash,而服务器 dist 里没有同名文件。
一步步来
1. 发布顺序:先资源后入口 — 必做
hash 静态资源先上线,入口 HTML 最后切换。这样新旧入口都能找到自己的资源。
2. 旧资源保留过渡期 — 必做
至少保留一个发布周期的旧资源(连续发布时尤其重要),让还持有旧入口的用户平滑过渡。
3. nginx fallback 不能吞静态资源 404 — 必做
try_files 先匹配真实文件,再回退 index.html,不能无差别 fallback:
location / {
try_files $uri $uri/ /index.html; # 先真实文件,后回退
}
4. CDN 与 Service Worker 遵循同一套版本一致性规则 — 必做
CDN 缓存策略和 SW 更新逻辑都要按"资源先于入口"设计,别让缓存层放大版本错位。
怎么确认修好了
用旧版本入口模拟老用户访问(预期形态):
curl -H "Cache-Control: no-cache" http://你的域名/feature-PcJGFbac.js
→ HTTP 200(新 hash 资源在)
curl -I http://你的域名/index.html
→ HTTP 200,引用资源列表与线上资源一致
发布后新旧页面均 HTTP 200(实测:保留旧资源后新旧页面均 200);连续发布多轮不再出现 ChunkLoadError。
其它环境的表现
| 环境 | 说明 |
|---|---|
| 单次发布 | 先资源后入口即可解决 |
| 连续发布 | 旧资源至少保留一个发布周期,否则上一轮用户仍会白屏 |
| nginx SPA fallback | 先 try_files $uri 再回退,别吞静态资源 404 |
| CDN / Service Worker | 与服务器同一套版本一致性规则 |
| 已白屏用户 | 强刷或重新打开即可恢复(缓存刷新后入口变新) |
症状
发布后部分用户白屏、刷新又偶尔恢复;控制台报 ChunkLoadError: Loading chunk N failed;动态 import 请求的带 hash 资源返回 404。
原因
版本错位:浏览器缓存的旧入口 HTML 仍引用旧版本 hash chunk,而新发布已删除旧资源 → 动态 import 404 → 模块加载失败 → 整页白屏。
解法
- 发布顺序:先资源后入口(hash 静态资源先上线,入口 HTML 最后切换)
- 旧资源保留过渡期(至少覆盖一个发布周期)
- nginx SPA fallback 不能吞静态资源 404(try_files 先匹配真实文件,再回退 index.html)
- CDN 与 Service Worker 遵循同一套版本一致性规则
验证证据
- 本地实测(2026-08-29):vite 5.4.21 两次 build,chunk hash 变化(feature-DP5yDwy7.js → feature-PcJGFbac.js);服务器只部署 v2 资源时旧 chunk HTTP 404(复现);保留旧资源后新旧页面均 HTTP 200(解法成立)。
- 实测复现日志(2026-08-29)
适用工具 (2)
本问题方案已挂到下列工具的方案页——从工具页也能回到这里,双向可达。
vite-deploynginx · 外部工具成套方案 (组合包)
这个问题包含在下列成套安装方案中。
- 网页部署验证 verified
来源与证据
← 构建与部署 问题域 | 问题货架 | 遇到其它问题?去 问题空间 提交求助卡