关键在于root拼接路径与try_files逐项匹配:root指定基础前缀,$uri拼接后查找文件,$uri/查目录,最后一项必须是存在的/index.html或内部URI,确保文件存在且权限可读。
用 root 指令配合 try_files 实现“文件不存在时返回默认页”,关键在于理解 root 的路径拼接逻辑和 try_files 的逐项匹配机制。不是简单写个 try_files $uri /index.html; 就能生效,必须确保路径解析正确、默认页存在、且不触发意外重定向或 404。
root 指令指定的是“基础路径前缀”,Nginx 会把请求 URI(如 /a/b/c.js)拼接到该路径后,形成实际文件路径。例如:
root /var/www/html; + 请求 /js/app.js → 查找 /var/www/html/js/app.js
root /data/site; + 请求 / → 查找 /data/site/(即尝试读取该目录下的 index 文件,或由 try_files 控制)注意:root 不影响 try_files 中的相对路径(如 /index.html),它仍以 root 值为基准解析。
try_files 按顺序检查每个参数是否对应真实文件(或目录)。最后一项不能是纯路径别名,而应是:一个存在的静态文件(如 /index.html),或一个内部 location(如 =404 或 @fallback)。常见错误是写成 try_files $uri /; —— 这会引发循环查找,因 / 又触发当前 location,可能 500 或无限重定向。
try_files $uri $uri/ /index.html;(优先找文件,再找目录,最后回退到 /var/www/html/index.html)try_files $uri $uri/ @vue; # 然后定义 location @vue { rewrite ^(.*)$ /index.html break; }
try_files $uri /;(无终止条件,易死循环)即使配置语法正确,若 /index.html 在 root 目录下不存在,或 Nginx 工作进程(如 www-data)无读取权限,仍会返回 404 或 403。建议:
ls -l /var/www/html/index.html 确认文件存在且属主/组可读http://your-domain.com/index.html 是否能打开index.html,其余路由由前端 JS 处理,因此兜底到它即可以下配置让所有非静态资源请求都落到 index.html,由前端路由接管:
server {listen 80;server_name example.com;root /var/www/my-spa;index index.html;location / {try_files $uri $uri/ /index.html;}# 可选:显式处理静态资源缓存location ~* .(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {expires 1y;add_header Cache-Control "public, immutable";}}
说明:$uri 匹配精确文件(如 /app.js),$uri/ 匹配目录(如请求 /blog/ 且该目录存在),最后 /index.html 是绝对路径(相对于 root),作为最终 fallback。