nginx本地部署react项目

127 阅读2分钟

前言

我们经常需要部署一个本地服务用于模拟线上环境进行测试,这时候就会遇到各种细节问题。

nginx安装

安装nginx有很多种方式,不同的系统可以使用对应的包管理器下载安装,这里通过homebrew安装。

安装homebrew

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

测试homebrew安装

brew -v

使用homebrew安装nginx

brew install nginx

测试nginx安装

nginx -v

启动nginx

sudo nginx

这将会直接启动nginx服务器,如果你想在后台运行,使用

sudo nginx -g "daemon off;"

关闭nginx

sudo nginx -s stop

nginx配置

找到配置文件,修改配置

nginx -t

显示的信息会提示nginx.conf文件的位置

nginx: configuration file /usr/local/etc/nginx/nginx.conf test failed

这里/usr/local/etc/nginx/nginx.conf

修改配置文件之前,建议先备份再修改。

如果配置的server_name是localhost,需要先修改hosts文件。

  • 打开 Finder。 

  • 按下 Cmd + Shift + G 来打开“前往文件夹”窗口。 

  • 在弹出的对话框中输入 /private/etc/,然后点击“前往”。 

  • 找到 hosts 文件,右键点击它,选择“打开方式” -> “文本编辑”。 

  • 如果需要,输入管理员密码以允许编辑。 

  • 在打开的 hosts 文件中进行需要的修改。 

  • 保存文件。

    127.0.0.1 localhost

403: permission denied

遇到nginx配置问题,先干两件事:

1、测试配置语法是否正确

sudo nginx -t

如果显示syntax is oktest is succussfull,则表示配置语法正确。

2、启用日志文件logs,增加 nginx 日志配置

error_log  logs/error.log;

访问之后,可以查看日志文件,一般会显示具体问题,比如某个文件拒绝访问,此时从两个方面入手:

1、修改react项目打包后的文件夹及其子目录访问权限

chmod -R 755 /path/to/directory

2、修改nginx用户配置,保证启动nginx的用户有权限访问

user  xiaohong admin;

注意: 这里最好加上用户xiaohong所在用户组admin,否则可能导致权限不足。

查看当前用户

whoami

查看用户组

groups

查看特定用户所在的用户组

id -Gn 用户名

3、修改完配置记得重启nginx

sudo nginx -s reload

404: 单页应用路由接管问题

比如:当我访问 "http://localhost:8080/" 是能正常访问页面的,但是当我直接通过 "http://localhost:8080/cat" 就会出现404了

  • React 项目路由注册案例

    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 ( <Route path="/" element={}> <Route index element={} /> <Route path='cat' element={} /> <Route path='dog' element={} /> ) }

    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 配置块如下:

server 块位于http块内部

# 主要的配置都在server块中
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 接管路由。

保存配置文件后,重新加载 Nginx 配置以应用更改:

sudo nginx -t  # 检查配置文件语法是否正确
sudo systemctl reload nginx  # 重新加载 Nginx

配置静态资源和禁止缓存

# 可选:显式配置静态资源(如 build/static/)的 location,有时有助于解决缓存或特定路径问题
location /static/ {
    alias dist/static/; # 注意结尾的 /
    # 可以设置更长的缓存时间
    expires max;
    access_log off;
}

# 禁止缓存 index.html,确保更新生效
location = /index.html {
    add_header Cache-Control "no-cache, no-store, must-revalidate";
    add_header Pragma "no-cache";
    add_header Expires "0";
}

现在直接访问 http://localhost:8080/cat 应该可以正常加载页面。

注意:访问时需要带上baseUrl和蓝绿部署路径,比如:http://localhost:8080/v2/base/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 体验AI代码助手 代码解读复制代码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 体验AI代码助手 代码解读复制代码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 或其他错误。

参考:

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