This is a very common question among newer React developers, and one question I had when I was starting out with React and Node.js. In this short example I will show you how to make create-react-app
work with Node.js and Express Back-end.
这在新的React开发人员中是一个非常常见的问题,也是我刚开始使用React和Node.js时遇到的一个问题。 在这个简短的示例中,我将向您展示如何使Node.js和Express Back-end可以使用create-react-app
。
Create a project using create-react-app
.
使用create-react-app
创建一个项目。
npx create-react-app example-create-react-app-express
Create a /client
directory under example-create-react-app-express
directory and move all the React boilerplate code created by create-react-app
to this new client directory.
在example-create-react-app-express
目录下创建一个/client
目录,并将所有由create-react-app
的React样板代码移动到该新客户端目录。
cd example-create-react-app-expressmkdir client
Create a package.json
file inside the root directory (example-create-react-app-express
) and copy the following contents:
在根目录( example-create-react-app-express
)内创建一个package.json
文件,并复制以下内容:
{
"name": "example-create-react-app-express",
"version": "1.0.0",
"scripts": {
"client": "cd client && yarn start",
"server": "nodemon server.js",
"dev": "concurrently --kill-others-on-fail \"yarn server\" \"yarn client\""
},
"dependencies": {
"body-parser": "^1.18.3",
"express": "^4.16.4"
},
"devDependencies": {
"concurrently": "^4.0.1"
}
}
Notice I am using concurrently
to run the React app and Server at the same time. The –kill-others-on-fail
flag will kill other processes if one exits with a non zero status code.
注意我正在concurrently
使用来concurrently
运行React应用程序和Server。 如果一个以非零状态码退出,则–kill-others-on-fail
标志将杀死其他进程。
Install nodemon
globally and the server dependencies:
全局安装nodemon
和服务器依赖项:
npm i nodemon -g
yarn
Create a server.js
file and copy the following contents:
创建一个server.js
文件并复制以下内容:
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const port = process.env.PORT || 5000;
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.get('/api/hello', (req, res) => {
res.send({ express: 'Hello From Express' });
});
app.post('/api/world', (req, res) => {
console.log(req.body);
res.send(
`I received your POST request. This is what you sent me: ${req.body.post}`,
);
});
app.listen(port, () => console.log(`Listening on port ${port}`));
This is a simple Express server that will run on port 5000 and have two API routes: GET
- /api/hello
, and POST
-/api/world
.
这是一个简单的Express服务器,将在端口5000上运行,并具有两个API路由: GET
/api/hello
和POST
/api/world
。
At this point you can run the Express server with the following command (still inside the root directory):
此时,您可以使用以下命令运行Express服务器(仍在根目录中):
node server.js
Now navigate to http://localhost:5000/api/hello
, and you will get the following:
现在导航到http://localhost:5000/api/hello
,您将获得以下信息:
We will test the POST
route once we build the React app.
构建React应用后,我们将测试POST
路由。
Now switch over to the client
directory where our React app lives.
现在切换到我们的React应用程序所在的client
目录。
Add the following line to the package.json
file created by create-react-app
.
package.json
下行添加到create-react-app
的package.json
文件中。
"proxy": "http://localhost:5000/"
The key to using an Express back-end server with a project created with create-react-app
is to use a proxy. This tells the Web-pack development server to proxy our API requests to our API server, given that our Express server is running on localhost:5000
.
将Express后端服务器与通过create-react-app
的项目一起使用的关键是使用代理。 假设我们的Express服务器在localhost:5000
上运行,这将告诉Web-pack开发服务器将我们的API请求代理到我们的API服务器。
Now modify ./client/src/App.js
to call our Express API Back-end, changes are in bold.
现在修改./client/src/App.js
来调用我们的Express API后端,更改以粗体显示。
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class App extends Component {
state = {
response: '',
post: '',
responseToPost: '',
};
componentDidMount() {
this.callApi()
.then(res => this.setState({ response: res.express }))
.catch(err => console.log(err));
}
callApi = async () => {
const response = await fetch('/api/hello');
const body = await response.json();
if (response.status !== 200) throw Error(body.message);
return body;
};
handleSubmit = async e => {
e.preventDefault();
const response = await fetch('/api/world', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ post: this.state.post }),
});
const body = await response.text();
this.setState({ responseToPost: body });
};
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
<p>{this.state.response}</p>
<form onSubmit={this.handleSubmit}>
<p>
<strong>Post to Server:</strong>
</p>
<input
type="text"
value={this.state.post}
onChange={e => this.setState({ post: e.target.value })}
/>
<button type="submit">Submit</button>
</form>
<p>{this.state.responseToPost}</p>
</div>
);
}
}
export default App;
We create callApi
method to interact with our GET
Express API route, then we call this method in componentDidMount
and finally set the state to the API response, which will be Hello From Express.
我们创建callApi
方法来与GET
Express API路由进行交互,然后在componentDidMount
调用此方法,最后将状态设置为API响应,即“ Hello From Express” 。
Notice we didn’t use a fully qualified URL http://localhost:5000/api/hello
to call our API, even though our React app runs on a different port (3000). This is because of the proxy
line we added to the package.json
file earlier.
请注意,即使我们的React应用程序在其他端口(3000)上运行,我们也没有使用完全限定的URL http://localhost:5000/api/hello
来调用我们的API。 这是因为proxy
我们之前添加到package.json
文件中的行。
We have a form with a single input. When submitted calls handleSubmit
, which in turn calls our POST
Express API route then saves the response to state and displays a message to the user: I received your POST request. This is what you sent me: [message from input].
我们有一个带有单个输入的表单。 提交时,调用handleSubmit
,然后依次调用我们的POST
Express API路由,然后将响应保存到状态并向用户显示一条消息: 我收到了您的POST请求。 这是您发送给我的:[来自输入的消息] 。
Now open ./client/src/App.css
and modify .App-header
class as follows (changes in bold)
现在打开./client/src/App.css
并按如下所示修改.App-header
类(更改为粗体)
.App-header {
...
min-height: 50%;
...
padding-bottom: 10px;
}
If you still have the server running, go ahead and stop it by pressing Ctrl+C in your terminal.
如果您仍在运行服务器,请在终端中按Ctrl + C停止它。
From the project root directory run the following:
从项目根目录运行以下命令:
yarn dev
This will launch the React app and run the server at the same time.
这将启动React应用程序并同时运行服务器。
Now navigate to http://localhost:3000
and you will hit the React app displaying the message coming from our GET
Express route. Nice ?!
现在导航到http://localhost:3000
,您将点击React应用,显示来自我们GET
Express路由的消息。 很好?!
Now, type something in the input field and submit the form, you will see the response from the POST
Express route displayed right below the input field.
现在,在输入字段中输入内容并提交表单,您将看到输入字段正下方显示的POST
Express路由的响应。
Finally take a look at at your terminal, you will see the message we sent from the client, that is because we call console.log
on the request body in the POST
Express route.
最后看看您的终端,您将看到我们从客户端发送的消息,这是因为我们在POST
Express路由的请求正文上调用console.log
。
Open server.js
and replace with the following contents:
打开server.js
并替换为以下内容:
const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const app = express();
const port = process.env.PORT || 5000;
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// API calls
app.get('/api/hello', (req, res) => {
res.send({ express: 'Hello From Express' });
});
app.post('/api/world', (req, res) => {
console.log(req.body);
res.send(
`I received your POST request. This is what you sent me: ${req.body.post}`,
);
});
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(`Listening on port ${port}`));
Open ./package.json
and add the following to the scripts
entry
打开./package.json
并将以下内容添加到scripts
条目中
"start": "node server.js",
"heroku-postbuild": "cd client && npm install && npm install --only=dev --no-shrinkwrap && npm run build"
Heroku will run the start
script by default and this will serve our app. Then we want to instruct Heroku to build our client app, we do so with heroku-postbuild
script.
Heroku默认会运行start
脚本,这将为我们的应用程序提供服务。 然后,我们要指示Heroku构建我们的客户端应用程序,我们使用heroku-postbuild
脚本来实现。
Now, head over to Heroku and log in (or open an account if you don’t have one).
现在,转到Heroku并登录(如果没有,请开设一个帐户)。
Create a new app and give it a name
创建一个新应用并命名
Click on the Deploy tab and follow the deploy instructions (which I think they are pretty self-explanatory, no point on replicating them here ?)
单击“ 部署”选项卡,然后按照部署说明进行操作(我认为它们很不言自明,没有必要在此处复制它们吗?)
And that is it, you can open your app by clicking on the Open app button at the top right corner within the Heroku dashboard for your app.
就是这样,您可以通过单击Heroku仪表板右上角的“ 打开应用程序”按钮来打开应用程序。
Visit the deployed app for this tutorial: https://cra-express.herokuapp.com/
请访问已部署的应用程序以获取本教程: https : //cra-express.herokuapp.com/
I write about other deployments options here:
我在这里写有关其他部署选项的信息:
This will be the final project structure.
这将是最终的项目结构。
Get the full code on the GitHub repository.
在GitHub存储库上获取完整代码。
Thank you for reading and I hope you enjoyed it. Any question, suggestions let me know in the comments below!
感谢您的阅读,希望您喜欢它。 如有任何疑问,建议请在下面的评论中告诉我!
You can follow me on Twitter, GitHub, Medium, LinkedIn or all of them.
您可以在Twitter , GitHub , Medium , LinkedIn或所有它们上关注我。
This post was originally posted on my personal blog website.
该帖子最初发布在我的个人博客网站上 。
Update 8/25/19: I have been building a prayer web app called "My Quiet Time - A Prayer Journal". If you would like to stay in the loop please sign up through the following link: http://b.link/mqt
19年8月25日更新:我一直在构建一个祷告网络应用程序,名为“ 我的安静时间-祷告日记 ”。 如果您想停留在循环中,请通过以下链接进行注册: http : //b.link/mqt
The app will be released before the end of the year, I have big plans for this app. To see some mockup screenshots follow the following link: http://pc.cd/Lpy7
该应用程序将在今年年底之前发布,我对此应用程序有很大的计划。 要查看一些模型截图,请点击以下链接: http : //pc.cd/Lpy7
My DMs on Twitter are open if you have any questions regarding the app
如果您对应用程序有任何疑问,我在Twitter上的 DM处于打开状态