单页应用 history 模式下刷新出现 404 的根本原因是 nginx 默认只返回真实文件,需用 try_files $uri $uri/ /index.html 实现静默回源;子路径部署须配合 alias 和调整 fallback 路径,并确保前端 router base 一致,同时避免 location 优先级冲突。

单页应用启用 history 模式后,刷新或直接访问 /user/profile 这类路径时出现 404,根本原因是 Nginx 默认只返回真实存在的文件,而这些路由实际由前端 JS 控制。要让服务器“兜底”返回 index.html,关键不是用 rewrite 做跳转,而是用 try_files 实现静默回源——它不改变 URL、不触发重定向,只是内部把请求交还给前端路由处理。
核心配置:用 try_files 替代 rewrite
rewrite 容易误用成 301/302 跳转(浏览器地址栏会变),或破坏原始路径导致资源加载失败;try_files 才是标准解法:
- 在
location /块内添加:try_files $uri $uri/ /index.html; -
$uri检查是否为真实文件(如/js/app.js)→ 存在则直接返回 -
$uri/检查是否为目录(如/assets/)→ 存在则尝试返回其索引页 - 前两者都失败时,静默返回
/index.html,由前端 router 解析当前 URL
子路径部署(如 /admin/)必须用 alias + 调整 fallback
如果应用部署在 https://example.com/admin/,不能写 root /dist;,否则 Nginx 会去查 /dist/admin/,而实际资源在 /dist/ 下:
- 改用
alias:确保末尾有斜杠,alias /var/www/dist/; - fallback 路径同步调整:
try_files $uri $uri/ /admin/index.html; - 同时确认前端
router的base设为/admin/,且构建时publicPath或base配置一致
避免 location 优先级冲突
try_files 只在当前 location 块生效。若存在更高优先级的匹配,请求根本进不到你的 location /:
- API 代理必须写在前面:
location /api/ { proxy_pass http://backend; } - 不要写
location ~ \.html$这类正则块,它可能提前截断/user请求并返回 404 - 精确匹配(
= /login)和^~开头匹配优先于location /,需检查是否意外覆盖了路由
验证配置是否生效
别只看页面是否能打开,要确认请求真的进了预期的 location:
- 执行
nginx -t检查语法,再nginx -s reload - 用
curl -I http://localhost/user查看响应头,状态码应为 200,且内容类型是text/html - 检查响应 body 是否为
index.html内容,而非 404 页面或空白











