spa刷新404并非轮询导致,而是静态资源未由nginx直接托管且未配置try_files兜底所致;应分离静态服务(root+try_files)与api代理(/api/→upstream),确保所有前端路由返回index.html。

Nginx 的轮询(round-robin)算法本身只负责将请求分发到多个后端服务器,它不处理前端路由或静态资源服务。所以“轮询导致 SPA 刷新 404”这个说法存在误解——404 不是轮询引起的,而是前端资源服务配置不当造成的。真正需要解决的,是在使用轮询作为负载均衡策略的同时,确保每个后端节点(或统一的静态资源节点)正确响应 SPA 的 history 路由请求。
关键在于:轮询 upstream 和前端静态服务要解耦,不能让轮询直接打到未配置 try_files 的后端应用服务器上。
✅ 正确的架构思路
SPA 的 index.html 和静态资源(JS/CSS/图片)应由 Nginx 直接提供(即 Nginx 做静态文件服务器),而不是转发给后端应用服务器(如 Node.js、Java 或 Python 服务)。
只有 API 请求才走 upstream 轮询代理。
所以配置重点不是“在轮询里防 404”,而是:
- 把静态资源和
index.html交给 Nginx 本地托管; - 所有非 API 的前端路由请求,全部由 Nginx 自己用
try_files处理; - API 请求单独匹配
/api/等路径,再 proxy_pass 到 upstream。
? 核心配置要点
1. 定义 upstream(仅用于 API,不用于页面)
upstream api_backend {
server 192.168.1.10:3000;
server 192.168.1.11:3000;
# 默认就是 round-robin,无需额外声明
}
2. server 块中分离静态服务与 API 代理
server {
listen 80;
server_name example.com;
root /var/www/my-spa; # 必须指向含 index.html 的 dist 目录
index index.html;
# ✅ 优先匹配静态资源,避免被 try_files 错误兜底
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2?|ttf|eot|webp)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# ✅ API 请求:严格以 /api/ 开头(尾部斜杠必须)
location /api/ {
proxy_pass http://api_backend/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# ✅ 主路由:所有其他请求(/、/about、/user/123)都 fallback 到 index.html
location / {
try_files $uri $uri/ /index.html;
}
}
⚠️ 注意:
location /api/的末尾/和proxy_pass http://api_backend/的末尾/都必须存在,否则路径拼接会出错(比如/api/users可能被错误转成/users)。
❌ 常见错误配置(会导致刷新 404)
- 把整个
location /都 proxy_pass 给 upstream(相当于把/about也转发给后端),而后端没实现该路由 → 返回 404; - upstream 里混入了静态资源服务节点,但这些节点没配
try_files,Nginx 转发过去后仍返回 404; -
try_files写在upstream块里(语法错误,Nginx 不允许); -
root路径错误,或用了alias替代root导致/index.html解析失败。
✅ 验证是否生效
- 直接访问
https://example.com/about(不存在的真实路径)→ 应返回200,且 HTML 内容是index.html; - 查看浏览器 Network 面板:JS/CSS 加载状态码为
200,无404; - 访问
https://example.com/api/users→ 应由 upstream 节点响应,且响应头含X-Upstream: 192.168.1.10类似标识(可加add_header X-Upstream $upstream_addr;调试)。
不复杂但容易忽略。











