create-react-app 和节点服务器的 ECONNREFUSED 错误
ECONNREFUSED error for create-react-app and node server
我正在使用 create-react-app(因此没有自定义 webpack)和节点服务器构建 MERN 应用程序。我正在使用 nodemon 重新启动后端的更改,问题是大约一半的时间我的前端似乎在 nodemon 可以重新启动节点服务器之前尝试渲染,导致 ECONNREFUSED 错误。
我可以通过简单地刷新页面来解决问题,但是必须反复执行此操作很烦人,我想弄清楚可能是什么问题。如果我 运行 节点服务器而不是 nodemon,则不会发生这种情况。
这是我客户端的相关部分package.json:
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
},
"proxy": "http://localhost:7777"
和服务器端package.json:
"scripts": {
"client-install": "npm intall --prefix client",
"start": "node server.js",
"server": "nodemon server.js",
"client": "cd client && npm start",
"dev": "concurrently \"npm run server\" \"npm run client\""
}
和我的server.js
const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const path = require('path');
const routes = require('./routes/index');
require('dotenv').config();
const app = express();
app.use(bodyParser.json());
mongoose.connect(process.env.DATABASE, {useNewUrlParser: true})
.then(() => console.log('MongoDb connected'))
.catch(err => console.log(`Mongo error ${err}`))
const port = process.env.PORT || 7777;
app.use('/', routes);
if (process.env.NODE_ENV === 'production') {
// Serve any static files
app.use(express.static(path.join(__dirname, 'client/build')));
// Handle React routing, return all requests to React app
app.get('*', function(req, res) {
res.sendFile(path.join(__dirname, 'client/build', 'index.html'));
});
}
app.listen(port, () => {
console.log(`Connected at port ${port}`)
})
我正在为我的前端 HTTP 请求使用 axios:
import axios from 'axios';
import FormData from 'form-data'
import keys from '../keys';
export const getPosts = () => {
return axios.get('/api')
}
export const post = (file, bodyInfo) => {
let formData = new FormData();
formData.append('file', file[0], file[0].name);
formData.append('bodyInfo', JSON.stringify(bodyInfo));
return axios.post('/api', formData, {
headers: {
'Content-Type': `multipart/form-data;
boundary=${formData._boundary}`,
}
})
}
export const getSinglePhoto = (id) => {
return axios.get(`/api/${id}`);
}
export const postUser = (userDetails) => {
console.log(userDetails);
return axios.post('/api/user', userDetails)
}
export const getUser = () => {
return axios.get('/user');
}
export const removeUser = (id) => {
return axios.delete(`/user/${id}`)
}
这是我的路线:
router.get('/api', postController.getPosts);
router.post('/api',
postController.type,
postController.uppic,
postController.cloudinary
);
router.get('/api/:id', postController.getSingle);
router.get('/user', userController.getUser);
router.post('/api/user', userController.postUser);
router.delete('/user/:id', userController.removeUser);
尝试使用 CORS
而不是 package.json
代理。我记得在使用时遇到 random/intermittent 连接问题。简而言之:端口 3000
上的前端 运行s 和 5000
上的 express
API 运行s。编译时,5000
和 express
上的 运行 都为编译后的前端 js 提供服务,其行为类似于 API.
设置非常相似,但没有连接问题:
快递服务器package.json
...
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "NODE_ENV=production node app.js",
"server": "NODE_ENV=development nodemon app.js",
"client": "npm run start --prefix client",
"dev": "concurrently \"npm run server\" \"npm run client\"",
"seeds": "NODE_ENV=development node seeds.js"
},
...
client/package.json(使用sass编译器,你可以use/ignore)。
...
"scripts": {
"build-css": "node-sass-chokidar --include-path ./src --include-path ./node_modules src/ -o src/",
"watch-css": "npm run build-css && node-sass-chokidar src/ -o src/ --watch --recursive",
"start-js": "react-scripts start",
"start": "npm-run-all -p watch-css start-js",
"build": "npm run build-css && react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
},
...
client/src/actions/axiosConfig.js(然后我创建一个 axios
配置自动指向我的 Express API 运行ning在 5000
)
import axios from 'axios';
export const app = axios.create({
baseURL: 'http://localhost:5000/api/',
withCredentials: true
})
client/src/actions/authActions.js(然后导入axios
配置)
import { app } from './axiosConfig';
const signinUser = props => dispatch => (
app.post(`signin`, { ...props })
.then(({data}) => {
dispatch({ type: types.SET_SIGNEDIN_USER, payload: data })
dispatch(fetchAvatarOnLogin());
})
.catch(err => dispatch({ type: types.SERVER_ERROR, payload: err }))
);
表示server.js(我用consign
导入所有文件):
const express = require('express');
const app = express();
const consign = require('consign');
consign({ locale: 'en-us', verbose: false})
.include('libs/middlewares.js')
.then("database")
.then("shared")
.then("services")
.then("controllers")
.then("routes")
.then('libs/server.js')
.into(app);
但是,等同于:
// APP REQUIRED IMPORTS
const express = require('express');
const app = express();
...etc
// APP MIDDLEWARES
...
app.use(cors({credentials: true, origin: http://localhost:3000})) // allows receiving of cookies from front-end
app.use(morgan('tiny')); // logging framework
app.use(bodyParser.json()); // parses header requests (req.body)
app.use(bodyParser.urlencoded({ extended: true })); // allows objects and arrays to be URL-encoded
...etc
// DATABASE CONFIG/CONN
// APP SHARED FUNCS
// APP SERVICES (passport, sendgrid mailer, ...etc)
// APP CONTROLLERS
...
signin: (req, res, done) => passport.authenticate('local-login', err => (
(err || !req.session) ? sendError(err || badCredentials, res, done) : res.status(201).json({ ...req.session }))
)(req, res, done)
...etc
// APP ROUTES
...
app.post('/api/signin', signin);
...etc
// EXPRESS SERVER
if (process.env.NODE_ENV === 'production') {
app.use(express.static('client/build'));
app.get('*', (req, res) => res.sendFile(path.resolve('client', 'build', 'index.html')));
}
app.listen(5000);
我正在使用 create-react-app(因此没有自定义 webpack)和节点服务器构建 MERN 应用程序。我正在使用 nodemon 重新启动后端的更改,问题是大约一半的时间我的前端似乎在 nodemon 可以重新启动节点服务器之前尝试渲染,导致 ECONNREFUSED 错误。
我可以通过简单地刷新页面来解决问题,但是必须反复执行此操作很烦人,我想弄清楚可能是什么问题。如果我 运行 节点服务器而不是 nodemon,则不会发生这种情况。
这是我客户端的相关部分package.json:
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
},
"proxy": "http://localhost:7777"
和服务器端package.json:
"scripts": {
"client-install": "npm intall --prefix client",
"start": "node server.js",
"server": "nodemon server.js",
"client": "cd client && npm start",
"dev": "concurrently \"npm run server\" \"npm run client\""
}
和我的server.js
const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const path = require('path');
const routes = require('./routes/index');
require('dotenv').config();
const app = express();
app.use(bodyParser.json());
mongoose.connect(process.env.DATABASE, {useNewUrlParser: true})
.then(() => console.log('MongoDb connected'))
.catch(err => console.log(`Mongo error ${err}`))
const port = process.env.PORT || 7777;
app.use('/', routes);
if (process.env.NODE_ENV === 'production') {
// Serve any static files
app.use(express.static(path.join(__dirname, 'client/build')));
// Handle React routing, return all requests to React app
app.get('*', function(req, res) {
res.sendFile(path.join(__dirname, 'client/build', 'index.html'));
});
}
app.listen(port, () => {
console.log(`Connected at port ${port}`)
})
我正在为我的前端 HTTP 请求使用 axios:
import axios from 'axios';
import FormData from 'form-data'
import keys from '../keys';
export const getPosts = () => {
return axios.get('/api')
}
export const post = (file, bodyInfo) => {
let formData = new FormData();
formData.append('file', file[0], file[0].name);
formData.append('bodyInfo', JSON.stringify(bodyInfo));
return axios.post('/api', formData, {
headers: {
'Content-Type': `multipart/form-data;
boundary=${formData._boundary}`,
}
})
}
export const getSinglePhoto = (id) => {
return axios.get(`/api/${id}`);
}
export const postUser = (userDetails) => {
console.log(userDetails);
return axios.post('/api/user', userDetails)
}
export const getUser = () => {
return axios.get('/user');
}
export const removeUser = (id) => {
return axios.delete(`/user/${id}`)
}
这是我的路线:
router.get('/api', postController.getPosts);
router.post('/api',
postController.type,
postController.uppic,
postController.cloudinary
);
router.get('/api/:id', postController.getSingle);
router.get('/user', userController.getUser);
router.post('/api/user', userController.postUser);
router.delete('/user/:id', userController.removeUser);
尝试使用 CORS
而不是 package.json
代理。我记得在使用时遇到 random/intermittent 连接问题。简而言之:端口 3000
上的前端 运行s 和 5000
上的 express
API 运行s。编译时,5000
和 express
上的 运行 都为编译后的前端 js 提供服务,其行为类似于 API.
设置非常相似,但没有连接问题:
快递服务器package.json
...
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "NODE_ENV=production node app.js",
"server": "NODE_ENV=development nodemon app.js",
"client": "npm run start --prefix client",
"dev": "concurrently \"npm run server\" \"npm run client\"",
"seeds": "NODE_ENV=development node seeds.js"
},
...
client/package.json(使用sass编译器,你可以use/ignore)。
...
"scripts": {
"build-css": "node-sass-chokidar --include-path ./src --include-path ./node_modules src/ -o src/",
"watch-css": "npm run build-css && node-sass-chokidar src/ -o src/ --watch --recursive",
"start-js": "react-scripts start",
"start": "npm-run-all -p watch-css start-js",
"build": "npm run build-css && react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
},
...
client/src/actions/axiosConfig.js(然后我创建一个 axios
配置自动指向我的 Express API 运行ning在 5000
)
import axios from 'axios';
export const app = axios.create({
baseURL: 'http://localhost:5000/api/',
withCredentials: true
})
client/src/actions/authActions.js(然后导入axios
配置)
import { app } from './axiosConfig';
const signinUser = props => dispatch => (
app.post(`signin`, { ...props })
.then(({data}) => {
dispatch({ type: types.SET_SIGNEDIN_USER, payload: data })
dispatch(fetchAvatarOnLogin());
})
.catch(err => dispatch({ type: types.SERVER_ERROR, payload: err }))
);
表示server.js(我用consign
导入所有文件):
const express = require('express');
const app = express();
const consign = require('consign');
consign({ locale: 'en-us', verbose: false})
.include('libs/middlewares.js')
.then("database")
.then("shared")
.then("services")
.then("controllers")
.then("routes")
.then('libs/server.js')
.into(app);
但是,等同于:
// APP REQUIRED IMPORTS
const express = require('express');
const app = express();
...etc
// APP MIDDLEWARES
...
app.use(cors({credentials: true, origin: http://localhost:3000})) // allows receiving of cookies from front-end
app.use(morgan('tiny')); // logging framework
app.use(bodyParser.json()); // parses header requests (req.body)
app.use(bodyParser.urlencoded({ extended: true })); // allows objects and arrays to be URL-encoded
...etc
// DATABASE CONFIG/CONN
// APP SHARED FUNCS
// APP SERVICES (passport, sendgrid mailer, ...etc)
// APP CONTROLLERS
...
signin: (req, res, done) => passport.authenticate('local-login', err => (
(err || !req.session) ? sendError(err || badCredentials, res, done) : res.status(201).json({ ...req.session }))
)(req, res, done)
...etc
// APP ROUTES
...
app.post('/api/signin', signin);
...etc
// EXPRESS SERVER
if (process.env.NODE_ENV === 'production') {
app.use(express.static('client/build'));
app.get('*', (req, res) => res.sendFile(path.resolve('client', 'build', 'index.html')));
}
app.listen(5000);