React+Nginx+Docker部署后刷新/api路由仅返回JSON的问题
问题描述
通过Docker Compose部署React前端+Nginx,Nginx将/api请求代理至backend:8080/api。正常通过页面按钮跳转访问example.com/api/userlist时,能正常显示页面并获取数据;但直接刷新或手动输入该URL时,返回后端原始JSON数据而非React页面。本地运行React无此问题,仅Nginx部署场景下出现。
相关配置文件
前端Dockerfile
# Base image FROM node:18.3.0-alpine AS build # Set working directory WORKDIR /app # Copy package.json and package-lock.json COPY package*.json ./ # Install dependencies RUN npm install # Copy source files COPY . . # Build application RUN npm run build # New base image FROM nginx:1.21.0-alpine # Copy build files from previous stage COPY --from=build /app/build/ /usr/share/nginx/html/ # start nginx CMD ["nginx", "-g", "daemon off;"]
Docker Compose文件
version: '3' services: frontend: build: ./front-end ports: - "80:80" depends_on: - backend backend: build: ./back-end ports: - "8080:8080"
当前Nginx配置
server { listen 80; server_name localhost; # Add root directory root /usr/share/nginx/html; #access_log /var/log/nginx/host.access.log main; # Add proxy for /api location /api { proxy_pass http://backend:8080/api; proxy_set_header Host $host; } location / { try_files $uri $uri/ /index.html; }
解决方案
问题核心是:Nginx的location /api会匹配所有以/api开头的请求,包括React客户端路由的/api/userlist。当用户直接刷新或输入该URL时,请求没有前端API请求的特征头,Nginx依然代理到后端返回JSON,而非返回React的index.html让前端路由处理。
解决思路是区分API请求和客户端路由请求,仅对真正的API请求做代理,其余返回React页面让前端路由处理。修改后的Nginx配置如下:
server { listen 80; server_name localhost; root /usr/share/nginx/html; # 处理/api路径:区分API请求与前端路由 location /api { # 仅当请求接受JSON格式时,代理到后端API if ($http_accept ~* "application/json") { proxy_pass http://backend:8080/api; proxy_set_header Host $host; break; } # 其他情况(前端路由请求)返回index.html try_files $uri $uri/ /index.html; } location / { try_files $uri $uri/ /index.html; } }
补充说明
- 前端axios/fetch发起API请求时,默认会携带
Accept: application/json请求头,这也是配置中判断的依据。 - 如果你的前端API请求未携带该头,可改用AJAX请求标识判断,将if条件替换为:
if ($http_x_requested_with = "XMLHttpRequest") { - 确保前端使用BrowserRouter(而非HashRouter),HashRouter路径带
#不会触发Nginx路径匹配问题,但URL不够直观。
内容的提问来源于stack exchange,提问作者nptad_William
相关产品推荐
相关产品推荐

