You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker部署Vite+Nginx的React应用仅根页面可访问,其他路由404

React容器化部署后子路由404问题解决

问题描述

使用Vite构建React应用,通过Nginx容器化部署后,本地5173端口测试时仅根页面http://localhost:5173可正常访问,访问http://localhost:5173/about等子路由时返回404 Not Found。

进入容器查看/usr/share/nginx/html目录内容:

50x.html    assets      index.html  speedtest

相关配置文件

Dockerfile

#### Stage 1: Build the react application
FROM node as build
WORKDIR /usr/src/app
COPY client/package*.json /usr/src/app
RUN npm install
COPY client/ /usr/src/app
RUN npm run build

#### Stage 2: serve the react application from Nginx for production environment
FROM nginx:1.21.4-alpine
COPY --from=build /usr/src/app/dist /usr/share/nginx/html
COPY client/nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80

CMD ["nginx","-g", "daemon off;"]

原nginx.conf

upstream backend {
    server internet-speed-backend:8080;
  }

server {

  listen 80;

  access_log /var/log/nginx/access.log;
  error_log /var/log/nginx/error.log;

  root /usr/share/nginx/html;
  index index.html index.htm;
  
  location @proxy-backend {
    try_files $uri $uri/ /index.html;
    proxy_pass http://backend;
    proxy_redirect off;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  
  }
}

Vite配置文件

import {resolve} from 'path'
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

const root = resolve(__dirname, 'src')
const outDir = resolve(__dirname, 'dist')

export default defineConfig({
  root,
  plugins: [react()],
  build: {
    outDir,
    emptyOutDir: true,
    rollupOptions: {
      input: {
        main: resolve(root, 'index.html'),
        speedtest: resolve(root, 'speedtest', 'speedtest.html')
      }

    }
  }
})

项目结构

── dist
│   ├── assets
│   ├── index.html
│   └── speedtest
│       └── speedtest.html
├── Dockerfile
├── nginx.conf
├── package.json
├── package-lock.json
├── public
├── src
│   ├── App.jsx
│   ├── assets
│   ├── components
│   ├── index.html
│   ├── main.jsx
│   ├── routes
│   │   ├── About.jsx
│   │   ├── Home.jsx
│   │   ├── Login.jsx
│   │   ├── Signup.jsx
│   │   ├── UserData.jsx
│   │   └── UserDataRow.jsx
│   ├── services
│   └── speedtest
├── vite.config.js
└── yarn.lock

问题原因

React是单页应用(SPA),前端路由由JavaScript在浏览器端处理,服务器上不存在/about这类路径对应的物理文件。原Nginx配置仅在@proxy-backend命名location中设置了try_files,但未匹配所有前端路由请求,导致Nginx找不到对应文件时直接返回404。

解决方案

修改Nginx配置,添加规则让所有非静态资源、非API的请求都转发到index.html,由React路由接管处理,同时单独处理静态资源和后端API:

upstream backend {
    server internet-speed-backend:8080;
}

server {
    listen 80;

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    root /usr/share/nginx/html;
    index index.html index.htm;

    # 处理静态资源,设置缓存提升性能
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    # 单独处理speedtest页面路由,指向对应的HTML文件
    location /speedtest {
        try_files $uri $uri/ /speedtest/speedtest.html;
    }

    # 所有前端路由请求转发到index.html,由React路由处理
    location / {
        try_files $uri $uri/ /index.html;
    }

    # 后端API转发(假设API路径以/api开头,根据实际调整)
    location /api {
        proxy_pass http://backend;
        proxy_redirect off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

配置说明

  1. 静态资源处理:匹配常见静态文件后缀,设置长期缓存,减少重复请求。
  2. speedtest路由:单独匹配/speedtest路径,确保该页面能正常访问。
  3. 前端路由兜底:location /中的try_files会先尝试访问文件或目录,不存在则转发到index.html,让React路由处理。
  4. 后端API转发:将API请求转发到后端服务,避免和前端路由冲突。

验证步骤

  1. 修改nginx.conf后重新构建Docker镜像:
docker build -t react-app .
  1. 重新启动容器,映射5173端口到容器80端口:
docker run -p 5173:80 react-app
  1. 访问http://localhost:5173/about等子路由,确认页面正常加载。

内容的提问来源于stack exchange,提问作者thor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 17:46:04