元数据
| id | vite-history-fallback | 收录 | 2026-08-29 |
|---|---|---|---|
| 问题域 | 构建与部署 | 主题分组 | 构建与部署 |
| 适用工具 | vite-deploynginx · 外部工具 | ||
症状
本地 `vite dev` 一切正常;打包部署到服务器后,直接访问首页正常、站内路由跳转正常,但**手动刷新子路由页面(深链)时白屏**,控制台里深链请求返回 404。
原因
vue-router 使用 `createWebHistory`(HTML5 History 模式)时,URL 不带 `#`。刷新时浏览器直接向服务器请求子路由路径(如 `/app/docs/setup`),服务器上没有这个物理文件,于是返回 404 → 白屏。`vite dev` 自带 history fallback,所以本地永远复现不了,问题只在部署后暴露。
解法
1. **base 一致性(排查第一步)**:`vite.config` 的 `base`、`createWebHistory(base)`、服务器部署目录三者必须完全一致(尤其结尾 `/`)。部分资源 404 / 图标丢失通常是 base 不一致。
2. **nginx history fallback(核心修复)**:把不存在的路径回退到 SPA 入口:
```nginx
location /app/ {
alias /path/to/dist/;
try_files $uri $uri/ /app/index.html;
}
```
3. **静态资源 404 不能被 fallback 吞掉(实测修正)**:无差别 fallback 会把缺失的 JS/CSS 也返回 200 + HTML,动态 import 失败时更难排查(与 ChunkLoadError 条目互相印证)。给 assets 单独一个 location,让真实 404 暴露:
```nginx
location /app/assets/ {
alias /path/to/dist/assets/;
try_files $uri =404;
}
```
4. **Apache 等价写法**:`RewriteEngine On` + 文件/目录不存在时 rewrite 到 `/app/index.html`(`.htaccess`,逻辑同 2)。
验证证据
- 本地实测(2026-08-29):nginx 1.28.3 + 最小 SPA fixture(`index.html` + `assets/`),`alias` 部署 + `curl` 断言。
- 复现:无 fallback 时 `GET /app/docs/setup` → 404(刷新白屏根因成立),`/app/index.html` → 200。
- 文章解法:`try_files ... /app/index.html` 后深链 → 200(HTML 入口);但 `GET /app/assets/missing.js` → 200 HTML —— 静态 404 被吞(文章未提的坑)。
- 修正后:深链 200、真实资源 200、缺失资源 404(正确暴露)。
- `实测复现日志(2026-08-29)`
来源与证据
素材来源:https://juejin.cn/post/7485263262508138523
验证证据:Evidence details kept locally (2026-08-29)