React本地代理在开发环境正常但serve启动后失效
问题:create-react-app项目构建后用serve启动代理失效
问题场景
用create-react-app创建的React项目,后端服务运行在localhost:3000,本地开发用npm run start(react-scripts启动)时代理正常工作,但执行npm run serve(用serve启动build产物)时,fetch请求失败,未走代理,报JSON解析错误。
现有配置信息
1. /src/.env
DANGEROUSLY_DISABLE_HOST_CHECK=true REACT_APP_API_URL=http://localhost:3000
2. /package.json
{ ... "proxy": "http://localhost:3000", ... "scripts": { "start": "PORT=4000 WDS_SOCKET_PORT=0 react-scripts start", "serve": "serve -s -p 4000 ./build > logfile.log 2>&1 &" } ... }
3. /src/setupProxy.tsx
import { createProxyMiddleware } from "http-proxy-middleware"; module.exports = function(app) { app.use( "/api", createProxyMiddleware({ target: "http://localhost:3000", changeOrigin: true, }) ); };
4. fetch请求代码
fetch(this.url, config) .then((res:any) => { return res.json(); }) .then((res:any) => { resolve(res); }) .catch((err:any) => { console.log(err); reject("Broken Fetch"); });
报错信息
SyntaxError: Unexpected token '<', "<!doctype "... is not valid JSON
原因分析
- react-scripts自带的代理机制(包括package.json中的
proxy字段和setupProxy.tsx配置)仅在开发环境(npm run start)生效,构建后的静态文件是纯前端资源,serve只是轻量静态文件服务器,不支持这些代理配置。 - 报错中的
<!doctype是前端index.html的内容,说明fetch请求没有发送到后端3000端口,而是被serve返回了首页文件(因为启用了-s参数,单页应用找不到对应资源时会fallback到index.html)。
解决方案
方案一:前端直接使用完整后端地址
确保fetch请求的URL使用完整的后端地址,比如将相对路径/api/xxx改为${process.env.REACT_APP_API_URL}/api/xxx。构建后REACT_APP_API_URL会被替换为http://localhost:3000,请求将直接发送到后端服务。
方案二:自定义带代理的静态服务器
用express搭建简单的静态服务器,同时配置代理规则,替代原生serve:
- 安装依赖:
npm install express http-proxy-middleware --save-dev - 创建
server.js文件:
const express = require('express'); const { createProxyMiddleware } = require('http-proxy-middleware'); const path = require('path'); const app = express(); // 代理/api路径到后端服务 app.use('/api', createProxyMiddleware({ target: 'http://localhost:3000', changeOrigin: true })); // 提供build目录下的静态文件 app.use(express.static(path.join(__dirname, 'build'))); // 单页应用路由 fallback app.get('*', (req, res) => { res.sendFile(path.join(__dirname, 'build', 'index.html')); }); const PORT = 4000; app.listen(PORT, () => { console.log(`Server running on port ${PORT}`); });
- 修改package.json的serve脚本:
"serve": "node server.js > logfile.log 2>&1 &"
方案三:后端配置CORS
在后端服务localhost:3000中配置CORS规则,允许http://localhost:4000的跨域请求,这样前端直接发送请求到后端地址时不会触发跨域限制。
内容的提问来源于stack exchange,提问作者TheLovelySausage
相关产品推荐
相关产品推荐

