SPA刷新子路由404的根本原因是Nginx按真实文件路径查找,而前端路由由JS接管;需用try_files $uri $uri/ /index.html配合静态资源location正则匹配来正确兜底。

单页应用(SPA)部署到 Nginx 后,刷新页面或直接访问子路由(如 /user/profile)时经常返回 404,根本原因在于:Nginx 默认按真实文件路径查找资源,而 SPA 的所有前端路由都由 JavaScript 在浏览器端接管,服务端根本没有对应的真实文件。
try_files 是怎么工作的
try_files 指令让 Nginx 按顺序检查指定的路径是否存在,只要找到一个存在的资源就直接返回;如果全部不存在,就跳转到最后一个参数(通常是命名 location 或状态码)。它不执行重定向,而是内部重写请求,性能高效且对前端透明。
典型用法:try_files $uri $uri/ /index.html;
含义是:先找有没有匹配 $uri 的静态文件(比如 /js/app.js),没有就看有没有同名目录(/about/),最后兜底到 /index.html —— 这正是 SPA 所需的“所有未知路由都交由 index.html 处理”的逻辑。
正确配置 location 块避免踩坑
很多同学把 try_files 写在 server 块顶层,结果导致 JS/CSS 等静态资源也被错误地 fallback 到 index.html,造成资源加载失败。关键是要让静态资源走正常路径,只对非资源路径做 fallback。
推荐结构:
- 用
location /匹配所有请求,但内部再细分 - 用
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2?|ttf|eot)$显式声明静态资源,确保它们被直接返回 - 主逻辑放在
location /中,搭配try_files $uri $uri/ /index.html;
完整可运行的 Nginx 配置示例
以下配置适用于 Vue CLI、Vite、Create React App 等主流构建工具生成的 SPA:
server {
listen 80;
server_name example.com;
root /var/www/my-spa;
index index.html;
<pre class="brush:php;toolbar:false;"># 优先匹配静态资源,防止被 try_files 错误兜底
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2?|ttf|eot|webp|pdf)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# 主路由处理:所有未命中静态资源的请求,都交给 index.html
location / {
try_files $uri $uri/ /index.html;
}}
注意:
- root 必须指向包含 index.html 的目录(不是 HTML 文件本身)
- 不要用 alias 替代 root,否则 $uri 拼接会出错
- 如果项目部署在子路径(如 /admin/),需配合前端 base 配置,并调整 location 和 try_files 路径
调试技巧:快速验证是否生效
改完配置别急着 reload,先做两件事:
- 运行
nginx -t确保语法正确 - 用
curl -I http://localhost/some-unknown-path查看响应头中的Content-Type:如果是text/html且状态码为 200,说明已成功 fallback 到 index.html - 打开浏览器开发者工具 → Network 标签,刷新子路由,确认
index.html返回 200,而 JS/CSS 仍各自返回 200(不是全变成 index.html)
如果发现静态资源也返回了 HTML 内容,大概率是正则 location 没生效,检查是否遗漏 ~* 或扩展名拼写错误。



















