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

如何同时运行Express服务器与React应用?端口冲突及最佳实践咨询

问题

之前在课堂团队项目里,能同时用npm start启动React应用、nodemon启动服务器,完全正常。现在用create-react-app搭建简单单页Web应用,发现没法让服务器和React共用3000端口,提示“端口3000已被占用”,搞不懂之前怎么实现同时运行的。

想问:二者通信是否需要共用同一端口?不管答案是是或否,对应的最佳实践是什么?

附当前项目代码:

server.js

const express = require('express')

const app = express()
const cors = require("cors")

app.use(cors)
app.use(express.json()) 

app.listen(3000, () => {
    console.log("Server is running")
})

package.json

{
  "name": "project",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.16.5",
    "@testing-library/react": "^13.4.0",
    "@testing-library/user-event": "^13.5.0",
    "cors": "^2.8.5",
    "dotenv": "^16.0.3",
    "express": "^4.18.2",
    "pg": "^8.8.0",
    "pg-hstore": "^2.3.4",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-scripts": "5.0.1",
    "sequelize": "^6.27.0",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "main": "./server/server.js"
}

之前试过用concurrently、npm-run-all工具,但React应用和服务器都没法正常运行。旧项目和当前项目的主要区别是旧项目服务器和React各有一个package.json,而且React的package.json里有"proxy": "http://127.0.0.1:4000"配置,我在当前项目里加了这个配置也没生效,现在旧项目除了npm start外没法修复。


解答

二者通信不需要共用同一端口

同一端口同一时间只能被一个进程占用,之前团队项目能同时运行,肯定是React和服务器用了不同端口,只是通过代理配置让你看起来像是在同一端口访问接口而已。

最佳实践分两种场景:

1. 开发环境

方案A:分离端口+React代理(推荐)

  • 给服务器换个端口,比如3001:修改server.js里的app.listen(3001, ...)
  • 在React的package.json里添加"proxy": "http://localhost:3001"
  • 启动方式:
    • 终端1:nodemon server.js 启动服务器
    • 终端2:npm start 启动React应用
    • React里调用接口时,直接写fetch('/api/xxx')就会被自动代理到http://localhost:3001/api/xxx

方案B:用concurrently同时启动(解决你之前工具失效的问题)

  • 修改package.json的scripts:
    "scripts": {
      "start": "react-scripts start",
      "server": "nodemon server/server.js",
      "dev": "concurrently \"npm run server\" \"npm start\""
    }
    
  • 确保服务器端口不是3000(比如改3001),并且React的proxy配置正确
  • 运行npm run dev就能同时启动两个服务

2. 生产环境

  • 打包React应用:npm run build
  • 在服务器代码里添加静态文件托管,让Express直接返回React的build文件:
    const path = require('path');
    app.use(express.static(path.join(__dirname, '../build')));
    
    // 处理SPA路由,刷新页面不会404
    app.get('*', (req, res) => {
      res.sendFile(path.join(__dirname, '../build/index.html'));
    });
    
  • 只需要启动服务器(比如3000端口),就能同时提供API服务和React静态页面,实现“同一端口访问”

你当前代码的问题

  • server.js里的app.use(cors)写错了,应该是app.use(cors())(要调用函数生成中间件),这会导致CORS配置失效,可能影响接口请求
  • 如果用了proxy配置,要确保服务器端口和proxy地址一致,而且React应用启动后,接口请求用相对路径才能触发代理

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 20:15:30