This article is a step-by-step guide on how to create a full stack React web application and set up the communication between the frontend part (client) and your backend part (server). So by the end of this tutorial you will have a ready-to-use boilerplate of a React app with node.js API ready for deployment.
Related Articles:
- 3 easy steps to create React application.
- How to create React Web App with a Node.js API Backend.
- How to make Axios Requests in React to a nodejs API.
- How to use React Hooks in Functional Components.
- 5 Steps to Set up React Development Environment.
- How to clone GitHub repository and branches.
- What are Component Lifecycle Methods in React.
- How to open Visual Studio code from Command Line.
- How to deploy React app to Heroku.
- Complete Guide on how to use Git and GitHub.
- How to get Request Origin in Express.js?
- How to get the Request Host in express.js?
- How to Get Current Date and Time in JavaScript.
Requires
Create React Front-end boilerplate
To generate a boilerplate version of a React application, we will use create-react-app node module. To install this module globally, we will use npm (node-package-manage) command.
$ npm install -g create-react-app
OR
$ sudo npm install -g create-react-app
Now that we have node and create-react-app module installed let’s create the frontend side for your app named my-react-web-app: Open your terminal and navigate to your projects folder, then run the following command, this may take some time:
$ create-react-app my-react-web-app
Then navigate to your application folder using the command:
$ cd my-react-web-app
After that, run the following command to open the blank folder my-react-web-app in your code editor, I Am using Visual Studio code. (for more details go here How to open Visual Studio code from Command Line)
$ code .
Create Node.js API back-end boilerplate
The Next step is to set up our server boilerplate code. In your project’s root directory, my-react-web-app, create a new folder with the name server.
$ mkdir server
Navigate to server folder and execute the npm init command from server folder.
$ cd server
$ npm init
Enter the name of your app and accept the default values for all questions, except for the question of entry point:
where
you should type server.js
instead of index.js and then hit the enter key. This will create a package.json file for your app.
The next step is to create the main file and the entry point of our server: server.js. Inside your server directory, create a new file: server.js and open it.
$ touch server.js
Now we are ready to set up our environment and install everything we need.
For creating and publishing our API, we will use the node.js framework Express. This framework is an amazing tool that allows you to launch quickly a functional API and you can combine it with many other packages. So first, we need to install Express by running this Command:
$ npm install --save express
Then install body parser package and setup body-parsing middleware in order to read the ‘body’ of an incoming JSON object in any response. But if you are using Express version 4.16+, the body-parser implementation is now included in the default Express package so there is no need for you to download and install another dependency, the only thing you have to do is adding this to your code.
$ app.use(express.json()); //use express bodyparser to parse JSON bodies
but, in our code we will install and use the usual body parser package.
$ npm install --save body-parser
After that, install CORS middleware with the cors package. For now, you can use the default settings. CORS package will help you configure the Allow-Control-Allow-Origin header inside the application code. This is much better than setting your headers with plain text in your application code.
$ npm install --save cors
Next, install Morgan to output request details on the console, store your HTTP requests and give you concise insight into how your app is being used, and where there could be potential errors or other issues that you haven’t yet explored. Morgan is useful when you have many middleware and you want to know the sequence of the request flow through various middleware in your application. It will help you understand every operation you perform during building or testing your API.
$ npm install --save morgan
Now, import all the packages you have just installed and setup the corresponding middlewares in your server.js file.
server.js
const express =require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const morgan = require('morgan');
const app = express();
app.use(bodyParser.json());
app.use(cors());
app.use(morgan('dev'));// we use morgan with the pre-defined format "dev" for developer.
module.exports = app;
To save your environment variables and not to use hard-coded number, in your server directory server create a new file .env then open it and add your API port: PORT variable to it. We use here the port 5000 but you can change it if you want.
$ touch .env
.env
PORT = 5000
To loads environment variables from .env file, first install dotenv package in you application
npm install --save dotenv
then add this line of code to your server.js.
require("dotenv").config();
Then define the constant PORT
const PORT= process.env.PORT;
Now, you can start the server listening on the provided PORT.
server.js
require("dotenv").config();
const express =require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const morgan = require('morgan');
const app = express();
const PORT= process.env.PORT;
app.use(bodyParser.json());
app.use(cors());
app.use(morgan('dev'));
app.listen(PORT, ()=>{
console.log(`server is listening on ${PORT}`);
});
module.exports = app;
To watch your server, you need to install nodemon, so you won’t need to restart your server every time you change your code.
$ npm install --save nodemon
Add the following code line to your package.json:
"start": "nodemon server.js "
So your Package.json will look like this:
//package.js
{
"name": "my-react-web-app",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "nodemon server.js "
},
"author": "",
"license": "ISC",
"dependencies": {
"body-parser": "^1.19.0",
"cors": "^2.8.5",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"morgan": "^1.10.0",
"nodemon": "^2.0.4",
"save": "^2.4.0"
}
}
To prevent pushing files and folders that are unnecessary and folders which may contain sensitive information such as passwords we need .gitignore file.
Create a new file with name .gitignore
inside server
folder
$ touch .gitignore
And copy the following lines to the .gitignore file:
node_modules
package-lock.json
.env
Connect React frontend app with node.js API backend
To make our front-end application communicate with node.js back-end API, and ensure that both are running on the same port we need to make some changes.
React front-end changes
Now, open the package.json
file inside the application root: my-react-web-app folder and change scripts from:
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
}
to
"scripts": {
"start-client": "react-scripts start",
"build": "react-scripts build && (cd server && npm install)",
"test": "react-scripts test",
"eject": "react-scripts eject",
"start": "cd server && npm start"
}
we changed the build script from
"build": "react-scripts build"
to
"build": "react-scripts build && (cd server && npm install)"
To make sure that when we run npm build, node_modules
folder will be installed and available before we run npm start.
Node.js back-end changes
Open package.json
inside the server folder and remove nodemon
from dependencies
. Then change the script start from:
"start": "nodemon server.js"
to
"start": "node server.js"
So your package.json
will look like this
//package.json
{
"name": "my-react-web-app",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js "
},
"author": "",
"license": "ISC",
"dependencies": {
"body-parser": "^1.19.0",
"cors": "^2.8.5",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"morgan": "^1.10.0",
"save": "^2.4.0"
}
}
In order run React front-end and Node.js back-end applications on the same port when we execute the npm build
command, and make sure that Express
server will render the contents of the .html file in build folder when we access http://localhost:5000/:
- add the following lines to the server.js.
NOTE: note that we have already our node.js API running on http://localhost:5000/.
const path = require('path');
const buildPath = path.join(__dirname, '..', 'build');
app.use(express.static(buildPath));
app.get('*', (req, res) => {
res.sendFile(path.join(buildPath, 'index.html'));
});
Now our front-end app and back-end app are running on the same port and we don’t need anymore cors. So the next change is to remove cors from dependencies
and the cors middleware from server.js.
Now the server.js and package.json will look like:
//package.json
{
"name": "my-react-web-app",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js "
},
"author": "",
"license": "ISC",
"dependencies": {
"body-parser": "^1.19.0",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"morgan": "^1.10.0",
"save": "^2.4.0"
}
}
//server.js
require("dotenv").config();
const express =require('express');
const bodyParser = require('body-parser');
const path = require('path');
const morgan = require('morgan');
const app = express();
const PORT= process.env.PORT;
app.use(bodyParser.json());
const buildPath = path.join(__dirname, '..', 'build');
app.use(express.static(buildPath));
app.get('*', (req, res) => {
res.sendFile(path.join(buildPath, 'index.html'));
});
app.use(morgan('dev'));
app.listen(PORT, ()=>{
console.log(`server is listening on ${PORT}`);
});
module.exports = app;
That’s all you need to ensure the communication between the react app and the node.js API boilerplates. Now you can continue your React application development. And once you are done with back-end and front-end development and you want to create your production build, run the following command in your application root:
$ npm run build
This command will run the script “react-scripts build && (cd server && npm install)” and create a build folder for the react application with node_modules folder.
To start you application on port 5000 run:
$ npm start

Congratulation! Now your app is ready to be deployed to a production environment. These links may be helpful in the deployment step:
You might also like:
3 easy steps to create React application.
How to create React Web App with a Node.js API Backend.
How to make Axios Requests in React to a nodejs API.
How to use React Hooks in Functional Components.
5 Steps to Set up React Development Environment.
How to clone GitHub repository and branches.
What are Component Lifecycle Methods in React.
How to open Visual Studio code from Command Line.
How to deploy React app to Heroku.
Complete Guide on how to use Git and GitHub.
How to get Request Origin in Express.js?
How to get the Request Host in express.js?
How to Get Current Date and Time in JavaScript.
How to add Custom Error Handler Middleware to your Node.js/Express API.
Complete JWT Authentication and Authorization System for MySQL/Node.js API.
How to Build a Complete API for User Login and Authentication using MySQL and Node.js.
Node.js + MySQL : Add Forgot/Reset Password to Login-Authentication System.
Nodemailer + Gmail: How to Send Emails from Node.js API using Gmail.
How to store Session in MySQL Database using express-mysql-session.
How to interact with MySQL database using async/await promises in node.js ?
How to use Sequelize async/await to interact with MySQL database in Node.js.
MANY-TO-MANY Association in MYSQL Database using Sequelize async/await with Node.js.
ONE-TO-ONE Association in MYSQL Database using Sequelize async/await with Node.js
ONE-TO-ONE Association in MYSQL Database using Sequelize async/await with Node.js.
How to add Routes to insert data into MySQL database-related tables in Node.js API?
Example How to use initialize() Function in Node.js/Express API .