必须配置Nginx路由重写,将不存在的前端路由请求兜底至index.html:使用try_files $uri $uri/ /index.html实现安全兜底,优先匹配真实文件与目录,失败则返回index.html;同时通过location ^~ /api/和静态资源正则规则排除干扰,确保API和静态资源正常访问。

前后端分离项目中,Vue、React 等单页应用(SPA)依赖前端路由(如 /system/user),但这些路径在浏览器刷新或直接访问时,并不对应真实服务器文件。Nginx 默认会尝试查找物理路径,找不到就返回 404。因此必须配置路由重写,把所有非 API、非静态资源的请求,统一兜底到 index.html,交由前端路由接管。
核心配置:用 try_files 实现安全兜底
这是最推荐、最稳定的方式,无需 rewrite 指令,语义清晰且不易出错:
-
location / 块中添加:
try_files $uri $uri/ /index.html; - 含义:先尝试匹配真实文件(
$uri),再尝试目录($uri/),都失败则返回/index.html - 它天然兼容静态资源(JS/CSS/图片)——只要文件存在,就不会被重写;只有不存在的路由才进 index.html
补充:排除 API 和静态资源路径
确保重写逻辑不干扰正常请求,需提前拦截关键路径:
-
API 请求:用
location ^~ /api/或location /api/明确代理,避免被try_files拦截 -
静态资源:可显式声明(如
location ~* \.(js|css|png|jpg|gif|ico)$),设置缓存并跳过重写;但通常try_files已足够智能,不必额外加 -
后端 context-path(如
/cnAdminRy):若后端有路径前缀,API 代理目标应为http://localhost:8080/cnAdminRy,且 location 匹配也需带前缀,例如location ^~ /cnAdminRy/
不推荐:用 rewrite + last 的方式
类似 rewrite ^(.*)$ /index.html last; 的写法看似简单,但存在风险:
- 可能误伤真实存在的静态资源(如
/js/app.js被重写导致 404) -
last会重新匹配 location,增加复杂度和潜在冲突 - 无法优雅处理子路径嵌套或带查询参数的 URL
完整 server 示例片段
以下是一个典型配置节选(省略 gzip、日志等通用项):
server {
listen 80;
server_name your-domain.com;
root /var/www/my-app/dist; # 指向前端构建后的 dist 目录
index index.html;
<pre class="brush:php;toolbar:false;"># 静态资源缓存(可选优化)
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2?)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# API 请求全部代理到后端
location ^~ /api/ {
proxy_pass http://localhost:8080/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# 兜底:所有其他请求返回 index.html
location / {
try_files $uri $uri/ /index.html;
}}
保存后执行 nginx -t && nginx -s reload 生效。重点在于 try_files 的顺序和 location ^~ /api/ 的优先级匹配——它比 location / 更精确,所以不会被兜底规则覆盖。



















