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

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:

  1. 安装依赖:npm install express http-proxy-middleware --save-dev
  2. 创建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}`);
});
  1. 修改package.json的serve脚本:
"serve": "node server.js > logfile.log 2>&1 &"

方案三:后端配置CORS

在后端服务localhost:3000中配置CORS规则,允许http://localhost:4000的跨域请求,这样前端直接发送请求到后端地址时不会触发跨域限制。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 16:05:53