React电商项目代理报错:ECONNREFUSED转ETIMEDOUT求助
React电商项目代理请求失败:ECONNREFUSED转为ETIMEDOUT
我正在开发基于React的电商项目,执行npm start启动前端后,频繁出现代理错误,无法将localhost:3000的请求代理到http://192.168.0.8:4000,错误类型从ECONNREFUSED变为ETIMEDOUT。
错误信息
Proxy error: Could not proxy request /api/v1/products?keyword=&page=1&price[gte]=0&price[lte]=25000&ratings[gte]=0 from localhost:3000 to http://192.168.0.8:4000. See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (ETIMEDOUT). Proxy error: Could not proxy request /Roboto-Regular.ttf from localhost:3000 to http://192.168.0.8:4000. See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (ETIMEDOUT). Proxy error: Could not proxy request /api/v1/me from localhost:3000 to http://192.168.0.8:4000. See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (ETIMEDOUT).
前端React项目package.json配置
{ "name": "frontend", "version": "0.1.0", "private": true, "dependencies": { "@material-ui/core": "^4.12.4", "@material-ui/icons": "^4.11.3", "@material-ui/lab": "^4.0.0-alpha.61", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.3.0", "@testing-library/user-event": "^13.5.0", "axios": "^0.27.2", "overlay-navbar": "^1.2.3", "react": "^18.2.0", "react-alert": "^7.0.3", "react-alert-template-basic": "^1.0.2", "react-dom": "^18.2.0", "react-helmet": "^6.1.0", "react-icons": "^4.4.0", "react-js-pagination": "^3.0.3", "react-material-ui-carousel": "^2.3.11", "react-rating-stars-component": "^2.2.0", "react-redux": "^8.0.2", "react-router-dom": "^6.3.0", "react-scripts": "^4.0.3", "react-toastify": "^9.0.3", "redux": "^4.2.0", "redux-devtools-extension": "^2.13.9", "redux-thunk": "^2.4.1", "web-vitals": "^2.1.4", "webfontloader": "^1.6.28" }, "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" ] }, "proxy": "http://192.168.0.8:4000" }
后端服务package.json配置
{ "name": "e-com", "version": "1.0.0", "description": "", "main": "backend/server.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "node backend/server.js", "dev": "nodemon backend/server.js" }, "author": "", "license": "ISC", "dependencies": { "bcryptjs": "^2.4.3", "body-parser": "^1.20.0", "cloudinary": "^1.30.1", "cookie-parser": "^1.4.6", "dotenv": "^16.0.1", "express": "^4.18.1", "express-fileupload": "^1.4.0", "jsonwebtoken": "^8.5.1", "mongoose": "^6.5.2", "nodemailer": "^6.7.8", "nodemon": "^2.0.19", "validator": "^13.7.0" } }
我已经尝试过给proxy地址添加斜杠、终止Node进程、重启系统,但均无效,错误仅从ECONNREFUSED变为ETIMEDOUT,寻求技术解决。
排查与解决方案
1. 确认后端服务的可达性
- 先验证后端是否正常运行:在前端机器终端执行
curl http://192.168.0.8:4000/api/v1/me(替换为实际存在的后端接口),如果无响应,先启动后端服务(执行npm run dev或npm start)。 - 检查网络连通性:执行
ping 192.168.0.8,如果丢包或不通,排查后端机器的防火墙、路由器设置,确保4000端口对外开放。
2. 替换内置代理为手动配置(适配react-scripts v4)
内置proxy存在局限性,改用http-proxy-middleware自定义代理:
- 安装依赖:
npm install http-proxy-middleware --save - 在前端
src目录新建setupProxy.js文件,添加以下代码:const { createProxyMiddleware } = require('http-proxy-middleware'); module.exports = function(app) { // 代理API请求 app.use( '/api', createProxyMiddleware({ target: 'http://192.168.0.8:4000', changeOrigin: true, timeout: 10000, // 延长超时时间,避免ETIMEDOUT }) ); // 代理静态资源(如字体文件) app.use( '/Roboto-Regular.ttf', createProxyMiddleware({ target: 'http://192.168.0.8:4000', changeOrigin: true, }) ); }; - 删除
package.json中的proxy字段,重启前端服务。
3. 修正后端服务监听地址
确保后端Express服务监听所有IP,而非仅本地:
// 后端server.js中修改监听代码 app.listen(4000, '0.0.0.0', () => { console.log(`Server running on http://192.168.0.8:4000`); });
如果之前是app.listen(4000),默认仅监听localhost,其他机器无法访问。
4. 排查端口占用与防火墙
- 后端机器检查4000端口占用:Windows执行
netstat -ano | findstr :4000,Linux/macOS执行lsof -i :4000,如有占用则杀死对应进程或更换端口。 - 临时关闭后端机器防火墙测试,或添加规则允许4000端口入站请求;前端机器防火墙也需确保允许访问
192.168.0.8:4000。
5. 调整超时设置
- 后端Express增加响应超时:
app.use((req, res, next) => { res.setTimeout(10000, () => { res.status(408).send('请求超时'); }); next(); }); - 前端Axios设置超时:
import axios from 'axios'; const axiosInstance = axios.create({ baseURL: '/api', timeout: 10000, // 10秒超时 });
内容的提问来源于stack exchange,提问作者yeshwanth yadav kondra
相关产品推荐
相关产品推荐

