如何在React应用同URL下搭建API(类Next.js,覆盖开发生产环境)
当然可以用 React 搭配 Express 实现和 Next.js 一样的效果——通过同一个端口同时访问 React 前端应用和 Express API 接口,下面分开发环境和生产环境给出具体实现方案:
开发环境配置
开发阶段 React 通常运行在默认的 localhost:3000,而 Express API 一般会放在另一个端口(比如 localhost:5000),通过配置代理就能实现同端口访问:
1. 搭建 Express API 服务
先写好你的 API 接口,示例代码:
// server.js const express = require('express'); const app = express(); // 示例API接口 app.get('/api/hello', (req, res) => { res.json({ message: 'Hello from Express API!' }); }); // 启动Express服务在5000端口 app.listen(5000, () => { console.log('Express API running on http://localhost:5000'); });
2. 配置 React 代理
根据你的 React 项目创建方式选择对应配置:
使用 create-react-app 创建的项目:
直接在项目根目录的package.json中添加一行代理配置:"proxy": "http://localhost:5000"重启 React 开发服务器后,访问
localhost:3000是 React 应用,访问localhost:3000/api/hello会自动转发到 Express 的 5000 端口接口。使用 Vite 创建的项目:
在vite.config.js中配置服务器代理:import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; export default defineConfig({ plugins: [react()], server: { proxy: { '/api': { target: 'http://localhost:5000', changeOrigin: true } } } });重启 Vite 服务后即可实现同端口访问效果。
生产环境配置
你已经通过 app.listen() 将 Express 部署到虚拟主机,只需把 React 打包后的静态文件交给 Express 托管,就能实现同端口访问:
1. 打包 React 应用
在 React 项目根目录执行打包命令:
# create-react-app 项目 npm run build # Vite 项目 npm run build
打包完成后会生成 build(create-react-app)或 dist(Vite)文件夹,里面是静态资源文件。
2. 修改 Express 配置托管静态文件
将打包后的静态文件夹放到 Express 项目目录下(比如命名为 client/build),然后修改 server.js:
const express = require('express'); const path = require('path'); const app = express(); // 保留你的API接口 app.get('/api/hello', (req, res) => { res.json({ message: 'Hello from Express API!' }); }); // 托管React静态文件 app.use(express.static(path.join(__dirname, 'client/build'))); // 处理SPA路由:所有非API请求返回React的index.html app.get('*', (req, res) => { res.sendFile(path.join(__dirname, 'client/build', 'index.html')); }); // 生产环境使用虚拟主机分配的端口,或默认5000 app.listen(process.env.PORT || 5000, () => { console.log('Production server running'); });
3. 部署到虚拟主机
将整个 Express 项目(包含托管的 React 静态文件)部署到你的虚拟主机,访问主机域名/IP 即可看到 React 应用,访问 /api/hello 即可调用 API 接口。
内容的提问来源于stack exchange,提问作者AliBot

