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; } }
配置说明
- 静态资源处理:匹配常见静态文件后缀,设置长期缓存,减少重复请求。
- speedtest路由:单独匹配
/speedtest路径,确保该页面能正常访问。 - 前端路由兜底:
location /中的try_files会先尝试访问文件或目录,不存在则转发到index.html,让React路由处理。 - 后端API转发:将API请求转发到后端服务,避免和前端路由冲突。
验证步骤
- 修改
nginx.conf后重新构建Docker镜像:
docker build -t react-app .
- 重新启动容器,映射5173端口到容器80端口:
docker run -p 5173:80 react-app
- 访问
http://localhost:5173/about等子路由,确认页面正常加载。
内容的提问来源于stack exchange,提问作者thor
相关产品推荐
相关产品推荐

