Nginx 静态资源(SPA)刷新 404 问题及解决方案

头像
2025年10月30日

在部署 Vue、React 或 Angular 等单页应用(SPA)时,通常会遇到以下问题: 访问首页正常。点击页面内的导航跳转也正常。但是,如果在页面直接刷新浏览器,或者直接在地址栏输入该链接,Nginx 会报404 Not Found 错误。

# nginx
Nginx 静态资源(SPA)刷新 404 问题及解决方案

1. 问题描述与背景

在部署 Vue、React 或 Angular 等单页应用(SPA)时,通常会遇到以下问题:

  • 访问首页 https://example.com/ 正常。
  • 点击页面内的导航跳转(如 https://example.com/about)也正常(因为是前端路由拦截)。
  • 但是,如果在 https://example.com/about 页面直接刷新浏览器,或者直接在地址栏输入该链接,Nginx 会报 404 Not Found 错误。

1.1 原配置(问题配置)

Nginx

server {
    listen       443 ssl;
    server_name  example.com;

    # SSL 配置省略...

    location / {
        root   /usr/share/nginx/html; # 假设的静态文件路径
        index  index.html index.htm;
    }
}

1.2 原因分析

默认情况下,Nginx 处理请求是基于文件系统的。 当请求 /about 时,Nginx 会去 root 目录下寻找名为 about 的文件。如果找不到,它会尝试寻找 about/ 目录下的 index.html。 对于 SPA 应用,/about 只是一个前端虚拟路由,服务器磁盘上并不存在这个物理文件或目录,因此 Nginx 最终抛出 404 错误。


2. 解决方案:使用 try_files

要解决这个问题,我们需要告诉 Nginx:“如果找不到对应的文件或目录,不要直接报 404,而是把请求全部内部重定向给 index.html,让前端代码自己去处理路由。”

2.1 优化后的配置

Nginx

server {
    listen       443 ssl;
    server_name  example.com;
  
    # 建议明确指定资源根目录
    root   /usr/share/nginx/html; 

    # SSL 配置部分保持不变...

    location / {
        # 核心修改:添加 try_files 指令
        # 尝试按顺序查找文件($uri)、目录($uri/),如果都失败,则返回 index.html
        try_files $uri $uri/ /index.html;
    }
}

3. try_files 指令详解

try_files 是 Nginx 中最强大的指令之一,其语法逻辑如下:

try_files $uri $uri/ /index.html;

这条指令的执行流程是从左到右依次检查:

  1. $uri
    • 检查用户请求的路径在磁盘上是否存在对应的具体文件(例如图片、JS、CSS 等)。
    • 如果存在,直接返回该文件。
  2. $uri/
    • 如果文件不存在,检查是否存在同名的目录
    • 如果存在目录,Nginx 会自动查找该目录下的 index 文件(如 /about/index.html)。
  3. /index.html
    • 如果前两者都不存在(既不是文件也不是目录),Nginx 将发起一个内部重定向,将请求转发给 /index.html
    • 此时,前端的 index.html 被加载,前端路由(Vue Router/React Router)接管 URL,根据路径渲染出正确的页面。

4. 补充说明 (Optional)

如果您的配置中需要严格的错误处理,也可以在最后加上 =404 作为兜底,但在 SPA 场景下通常不需要,除非您确定 index.html 可能丢失。

Nginx

# 变体写法:如果 index.html 也不存在,才报 404
try_files $uri $uri/ /index.html =404;