Nginx 如何把所有请求都指向单个 HTML 页面?
Nginx 所有请求回退到单个 HTML(SPA 路由支持):try_files $uri $uri/ /index.html 配置;静态资源例外处理、history 路由 404 问题、缓存建议与 FAQ。
用 try_files 回退到入口页——这是单页应用(SPA)history 路由的标准 Nginx 配置:
server {
listen 80;
server_name example.com;
root /var/www/myspa;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}
含义:先按 URI 找真实文件 → 再找目录 → 都找不到就返回 /index.html,由前端路由接管。
为什么需要它
SPA(React/Vue/Angular)的路由在浏览器里完成:/user/42 这个路径在服务器上并不存在对应文件。直接访问或刷新这种 URL 时,若不做回退,Nginx 老老实实返回 404——这就是"SPA 刷新就 404"的经典问题。try_files 把所有"找不到"的路径兜底给 index.html,让 JS 路由决定渲染什么。
生产环境完整版
server {
listen 80;
server_name example.com;
root /var/www/myspa/dist;
index index.html;
# 静态资源:存在即返回,长缓存(构建产物带 hash 才安全)
location /assets/ {
try_files $uri =404;
expires 30d;
add_header Cache-Control "public, immutable";
}
# API 请求别回退给 index.html,反代到后端
location /api/ {
proxy_pass http://backend:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# 其余全部回退到入口页
location / {
try_files $uri $uri/ /index.html;
}
# index.html 本身不缓存,保证发版即生效
location = /index.html {
add_header Cache-Control "no-cache";
}
}
要点:
- API 和静态资源要单独分流,不能一律回退——否则 404 的接口请求会返回 HTML,客户端解析出错还以为是后端问题。
- index.html 禁缓存:它是指向最新构建产物的入口,被缓存了用户就拿不到新版本。
观测云对照
SPA 前端"白屏/路由错乱"类投诉,很多其实发生在交付层:静态资源 404、index.html 被缓存成旧版。把 Nginx 访问日志接入观测云,按 URI 聚合 404——发版后 /assets/ 下 404 突增,多半是新 HTML 引用了旧资源(缓存不一致);配合 RUM 真实用户监控,前端加载失败、白屏率直接按版本维度呈现。
常见问题(FAQ)
Q:配置了 try_files 还是 404?
A:按序排查:root 路径对吗(dist 目录别指漏)?index.html 文件在吗?Nginx 用户对该路径有读权限吗(403 会伪装成别的问题)?
Q:hash 路由(/#/path)需要这个配置吗?
A:不需要。hash 部分不发给服务器,/ 永远能命中 index.html。只有 history 模式(无 # 的干净 URL)才需要回退配置。
Q:回退后接口返回 HTML 导致前端报错?
A:说明 API 请求没被 /api/ location 拦截而落进了回退规则。检查 location 前缀与前端请求路径是否对齐。