vue react前端项目打包部署后访问完整路由404【解决方案】

前言

  • 当我们开发好的SPA前端项目打包部署到nginx等web容器中后,遇到了404的路由访问问题,比如:当我访问 "http://192.168.1.102:8080/" 是能正常访问页面的,但是当我直接通过 "http://192.168.1.102:8080/cat" 就会出现404了
  • 所以,这是什么原因呢?

原因说明

  • React 项目路由注册案例
tsx 复制代码
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom'
import './App.css'
import RootLayout from './pages/RootLayout'
import Cat from './pages/Cat'
import Dog from './pages/Dog'

function App() {

  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<RootLayout />}>
          <Route index element={<Navigate to='/cat' replace />} />
          <Route path='cat' element={<Cat />} />
          <Route path='dog' element={<Dog />} />
        </Route>
      </Routes>
    </BrowserRouter>
  )
}

export default App

问题原因

  1. React Router 的客户端路由原理
    React Router 使用的是客户端路由 ,它依赖于 JavaScript 在浏览器端动态渲染页面。当你访问 http://localhost:8080/ 时,浏览器会加载你的应用的 index.html,然后 React Router 根据当前的 URL 动态渲染对应的组件(例如 MyDay 组件)。在这种情况下,Nginx 只需要正确返回 index.html,React Router 就会接管路由。
  2. 直接访问子路由(如 /cat)时的行为
    当你直接访问 http://localhost:8080/cat 时,浏览器会向 Nginx 发送一个请求,试图获取 /cat 对应的资源。然而,Nginx 并不知道 /cat 是一个客户端路由,它会尝试在文件系统中寻找 /cat 对应的静态文件(例如 /cat/index.html)。由于你的 React 项目是单页应用(SPA),并没有 /cat 这样的静态文件,因此 Nginx 返回了 404 错误。
  3. 为什么访问根路径 / 没有问题?
    当你访问 http://localhost:8080/ 时,Nginx 会正确返回 index.html,然后 React Router 在浏览器端接管路由,并根据路由配置渲染正确的页面。

你的问题是由于 React Router 和 Nginx 的路由处理方式不匹配导致的。下面我会详细解释问题的原因,并提供解决方案。

解决方案

为了解决这个问题,你需要在 Nginx 的配置中确保所有未知的路由请求(例如 /cat)都返回 index.html,从而让 React Router 在浏览器端接管路由。以下是详细的解决方案:

方案 1:在 Nginx 中配置路由重定向

你需要修改 Nginx 的配置文件,添加一个规则,确保所有未匹配的路径都返回 index.html。假设你的 React 项目构建后的文件存放在 /usr/share/nginx/html 目录下(或者你自己的部署目录),可以按以下方式配置:

  1. 打开 Nginx 配置文件(通常位于 /etc/nginx/nginx.conf/etc/nginx/conf.d/ 目录下)。
  2. 添加或修改 server 配置块如下:
nginx 复制代码
server {
    listen 8080;
    server_name localhost;

    root /usr/share/nginx/html; # 替换为你的 React 项目构建文件的实际路径
    index index.html;

    location / {
        try_files $uri $uri/ /index.html; # 核心配置
    }
}

解释:

  • try_files $uri $uri/ /index.html; 是关键配置。它的意思是:
    • 首先尝试查找请求的 $uri(例如 /cat)。
    • 如果找不到,则尝试查找 $uri/(例如 /cat/)。
    • 如果仍然找不到,则将请求重定向到 /index.html,由 React Router 接管路由。
  1. 保存配置文件后,重新加载 Nginx 配置以应用更改:
bash 复制代码
sudo nginx -t  # 检查配置文件语法是否正确
sudo systemctl reload nginx  # 重新加载 Nginx
  1. 现在直接访问 http://localhost:8080/cat 应该可以正常加载页面。

方案 2:使用 HashRouter 替代 BrowserRouter

如果你无法修改 Nginx 配置(例如在某些托管环境中),可以考虑在 React 项目中使用 HashRouter 替代 BrowserRouterHashRouter 使用 URL 的哈希部分(例如 http://localhost:8080/#/cat)来管理路由,这种方式不需要服务器端的支持。

  1. 修改你的 React 代码,将 BrowserRouter 替换为 HashRouter

  2. 重新打包部署你的项目。

优点:

  • 不需要修改服务器配置,适合无法控制服务器环境的情况。

缺点:

  • URL 中会多出一个 # 符号(例如 http://localhost:8080/#/cat),可能不符合 SEO 要求或美观需求。

方案 3:使用其他服务器配置(如果不使用 Nginx)

如果你使用的不是 Nginx,而是其他服务器(如 Apache 或 Express),也需要类似的配置:

  • Apache 配置:

    .htaccess 文件中添加以下内容:

    apache 复制代码
    RewriteEngine On
    RewriteBase /
    RewriteRule ^index\.html$ - [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /index.html [L]
  • Express.js 配置:

    如果使用 Node.js 的 Express 服务器,确保所有未匹配的路由都返回 index.html

    javascript 复制代码
    const express = require('express');
    const path = require('path');
    const app = express();
    
    app.use(express.static(path.join(__dirname, 'build')));
    
    app.get('*', (req, res) => {
      res.sendFile(path.join(__dirname, 'build', 'index.html'));
    });
    
    app.listen(8080);

推荐方案

  • 如果你有权限修改服务器配置,推荐使用 方案 1(Nginx 配置),因为这是最常见且最优雅的解决方案,适用于绝大多数单页应用(SPA)。
  • 如果你无法修改服务器配置,或者只是临时测试,推荐使用 方案 2(HashRouter)

测试验证

  1. 部署完成后,尝试以下操作:

    • 直接访问 http://localhost:8080/,验证是否正常跳转到 /cat
    • 直接访问 http://localhost:8080/cat,验证是否能正确加载页面。
    • 直接访问 http://localhost:8080/dog,验证是否能正确加载页面。
  2. 如果仍有问题,可以检查以下几点:

    • 确认 Nginx 配置是否正确应用(可以用 nginx -T 查看当前生效的配置)。
    • 确认 React 项目的构建文件是否正确部署到 Nginx 的 root 目录下。
    • 查看浏览器开发者工具中的网络请求,确认是否返回了 404 或其他错误。

总结

你的问题是典型的单页应用(SPA)部署问题,核心原因是服务器端没有正确处理客户端路由。通过在 Nginx 中配置 try_files 规则,可以确保所有路由请求都返回 index.html,从而让 React Router 接管路由。如果无法修改服务器配置,可以使用 HashRouter 作为替代方案。

相关推荐
百万蹄蹄向前冲18 分钟前
组建百万前端梦之队-计算机大学生竞赛发展蓝图
前端·vue.js·掘金社区
云隙阳光i31 分钟前
实现手机手势签字功能
前端·javascript·vue.js
imkaifan1 小时前
vue2升级Vue3--native、对inheritAttrs作用做以解释、声明的prop属性和未声明prop的属性
前端·vue.js·native修饰符·inheritattrs作用·声明的prop属性·未声明prop的属性
小程序设计1 小时前
【2025】基于springboot+vue的宠物领养管理系统(源码、万字文档、图文修改、调试答疑)
vue.js·spring boot·宠物
小程序设计1 小时前
【2025】基于springboot+vue的体育场馆预约管理系统(源码、万字文档、图文修改、调试答疑)
vue.js·spring boot·后端
柠檬树^-^2 小时前
app.config.globalProperties
前端·javascript·vue.js
太阳花ˉ2 小时前
react(一):特点-基本使用-JSX语法
前端·react.js
赵大仁2 小时前
深入解析 React Diff 算法:原理、优化与实践
前端·react.js·前端框架
1024小神2 小时前
vue/react/vite前端项目打包的时候加上时间最简单版本,防止后端扯皮
前端·vue.js·react.js
起来改bug2 小时前
【pptx-preview】react+pptx预览
javascript·react.js·pptx