构建与部署 · 收录于 2026-08-29 · 适用 2 工具 ✓ 实测验证

Vue3 + Vite history 路由部署后刷新白屏(404)

已验证 2026-08-29history 路由刷新白屏 404——nginx try_files 回退 SPA 入口(/app/index.html),静态资源单独暴露 404 不误回退。

快速修复

# 一键:nginx 核心修复——不存在的路径回退到 SPA 入口,静态资源 404 单独暴露
# location /app/ { alias /path/to/dist/; try_files $uri $uri/ /app/index.html; }
# location /app/assets/ { alias /path/to/dist/assets/; try_files $uri =404; }

把这两段 location 按你的部署目录改好,nginx -t && nginx -s reload。

你会遇到什么

本地 vite dev 一切正常;打包部署到服务器后,访问首页正常、站内路由跳转也正常,但手动刷新子路由页面(深链)时白屏,控制台里深链请求返回 404。本地永远复现不了,问题只在部署后暴露。

本文路径:快速修复(30 秒一段命令)→ 一步步排查(可跳读)→ 原理与变体(症状/原因/证据)。赶时间直接跳到「快速修复」。

为什么会这样

vue-router 用 createWebHistory(HTML5 History 模式)时,URL 不带 #。刷新时浏览器直接向服务器请求子路由路径(如 /app/docs/setup),服务器上没有这个物理文件,于是返回 404 → 白屏。vite dev 自带 history fallback,所以本地永远正常。

场景表现
站内跳转✅ 前端路由接管,不发服务器请求
刷新深链❌ 浏览器直接请求 /app/docs/setup,服务器无此文件 → 404
首页直接访问✅ 物理文件存在

HTML5 History 模式(createWebHistory)把路由状态放进 URL 路径,刷新时浏览器不经过前端路由,直接向服务器发完整路径的请求——服务器按物理文件找 /app/docs/setup,找不到就 404。站内跳转不触发服务器请求(前端 router 拦截),所以「站内导航正常、一刷新就白屏」是这类问题的标志性特征。

vite dev 内置 history fallback(所有路径回退到 index.html),本地永远正常,部署后消失——这是「开发环境与生产环境静态服务器行为不同」的典型。

确定性推论:生产服务器必须配「未知路径回退到 index.html」:nginx try_files $uri $uri/ /index.html;、静态托管平台开 SPA fallback、或 Node 服务器 app.get('*', ...) 返回 index.html;配好后刷新深链返回 200 而不是 404 即修复。

一步步来

1. 排查第一步:base 一致性 — 排查

vite.config 的 base、createWebHistory(base)、服务器部署目录三者必须完全一致(尤其结尾 /)。部分资源 404 / 图标丢失通常是 base 不一致。

2. nginx history fallback(核心修复) — 必做

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:

location /app/assets/ {
  alias /path/to/dist/assets/;
  try_files $uri =404;
}

4. Apache 等价写法 — 必做

.htaccess:RewriteEngine On + 文件/目录不存在时 rewrite 到 /app/index.html(逻辑同第 2 步)。

怎么确认修好了

curl 断言三类路径(预期输出):

curl -I http://你的域名/app/docs/setup
→ HTTP 200(深链回退到 HTML 入口)
curl -I http://你的域名/app/assets/main.js
→ HTTP 200(真实资源)
curl -I http://你的域名/app/assets/missing.js
→ HTTP 404(缺失资源正确暴露,不被吞)

浏览器刷新任意深链不再白屏(实测:修正后深链 200、真实资源 200、缺失资源 404)。

其它环境的表现

环境说明
nginx alias 部署深链回退 + assets 独立 location(实测修正方案)
nginx root 部署同样 try_files $uri $uri/ /index.html,注意 base 路径
Apache.htaccess rewrite,逻辑相同
base 不一致部分资源 404 / 图标丢失,先查 base 再查 fallback
无差别 fallback缺失 JS 也返回 200 HTML,排查更难(实测踩坑)

症状

本地 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 入口:
   location /app/ {
     alias /path/to/dist/;
     try_files $uri $uri/ /app/index.html;
   }
  1. 静态资源 404 不能被 fallback 吞掉(实测修正):无差别 fallback 会把缺失的 JS/CSS 也返回 200 + HTML,动态 import 失败时更难排查(与 ChunkLoadError 条目互相印证)。给 assets 单独一个 location,让真实 404 暴露:
   location /app/assets/ {
     alias /path/to/dist/assets/;
     try_files $uri =404;
   }
  1. 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)

适用工具 (2)

本问题方案已挂到下列工具的方案页——从工具页也能回到这里,双向可达。

vite-deploynginx · 外部工具

成套方案 (组合包)

这个问题包含在下列成套安装方案中。

来源与证据

收录 验证 ✓ 实测验证适用 2 工具
方案含本地实测或来源可复核的解法;未实测项已在文中如实标注。

素材来源:https://juejin.cn/post/7485263262508138523

← 构建与部署 问题域 | 问题货架 | 遇到其它问题?去 问题空间 提交求助卡