Create and Deploy Your First React Web App with a Node.js Backend

A step-by-step guide to creating and deploying a full stack web application ✌️

Conor Deegan
Jun 9, 2020 · 17 min read

Creating and deploying a modern web application can be difficult. Between the countless software options available, the neverending documentation, and the myriad of opinions — deciding where to start can seem impossible.

The aim of this article is to offer a step-by-step guide demonstrating one of the ways a modern web application can be created, structured, and deployed to a production environment. It will demonstrate how to structure your repository, set up a communication protocol between your client and server, and continuously deploy your application to the web. By the end of this article, you will have a solid foundation for a web application, freeing up time and resources to focus on developing your actual app and business logic.

You will need a (very) basic understanding of Node.js, React, npm, and working with the command line for this tutorial. We will also use Heroku, GitHub, and VSCode as our IDE.

The final code for this tutorial can be found in this Github repository.

What we will cover

  • Initial requirements and package installation ✅
  • Repository structure ✅
  • React frontend boilerplate ✅
  • Node.js backend boilerplate ✅
  • Frontend and backend communication ✅
  • Preparation for deployment to production ✅
  • Deployment to production ✅
  • Pushing updates to your production application ✅

1. Initial requirements and package installation

To get started you will need to download some packages to set up your development environment, skip this section if you already have them installed.

Node.js

You can download the Node.js source code from their official download page. Simply choose the LTS version (currently v12.16.3) for your operating system and follow the download instructions.

Once complete, you can verify that the download was successful. Open a new terminal window and type the following command and hit enter:

node -v

If Node.js was installed successfully the version number should be printed in your console. Something like this:

This number may differ depending on which version of Node.js you have installed.

Npm

Npm is distributed with Node.js – which means that when you download Node.js, you automatically get npm installed on your computer also.

To confirm that you have npm installed you can run the following command in your terminal:

npm -v

Similarly to our previous command, the npm version number should be printed in your console. Something like this:

Git

You will also need to install git. This can be downloaded from their official download page. Again, simply choose the LTS version for your operating system and follow the download instructions.

To verify your that your download was successful you can run the following command in your terminal window: (last one, I promise!)

git --version

The git version number should be printed to your console:

2. Repository Structure

Create a repository

Now that you have installed the necessary packages, you can begin to set up your repository.

Although you can create and push a new repository to Github entirely through the command line, for ease we will start by creating our repository on Github.com directly.

Once logged in to your Github account you can create a new repository here.

Simply enter a repository name, choose whether you would like your repository to be public or private (to avoid issues I recommend choosing public for the time being), and select to ‘Initialize this repository with a README’. Once you have completed this you can go ahead and create your repository.

Clone your repository

Once your repository has been created, it needs to be ‘cloned’ from Github to your computer. We will do this in a couple of steps.

First, copy and paste your git repository url which can be found here:

We will then switch back over to our terminal. If you are not comfortable with the command line, this is where things can seem tricky.

When you open your terminal, you will see something like this: (or the equivalent for your OS)

This is the root directory. Go ahead and change to the directory you would like to save this project to. To change directory you can run the change directory command followed by the name of the directory. For instance, to get to your desktop from here you can type to following command:

cd Desktop/

You should see something like the following in your terminal:

You are now ready to clone your Github repository to your computer. Go ahead and paste the command below into your terminal window, don’t forget to replace the link with the link you copied from Github.com in step 1.

git clone https://github.com/<username>/<repo-name>.git

This command clones your git repository from Github to your desktop. After running this command you will be able to see your repository folder saved to your Desktop (or whichever directory you chose to use).

Create a package.json file

Now that your repository is saved locally on your computer, it can be opened in VSCode. If you do not already have VSCode installed, you can do so here.

In the top left, you can see the name of your repository, in this case, ‘web-app-boilerplate’. In the left-hand menu you can see the files in the repository, currently the only file is the README.md.

Next, open the terminal in VSCode (View > Terminal). This will open a terminal window in the project’s root directory.

Now that we have our terminal open in VSCode, we need to create a package.json file. All Node.js projects using npm require a package.json file. This file holds various metadata relevant to the project such as the projects name, description, dependencies, version number, and configuration data.

To create this file run the following command in the VSCode terminal (from this point on, all commands will be run in the VSCode terminal in the root of the project directory):

npm init

This command will launch a process that will ask a couple of questions in order to seed our package.json file with some basic information. We can simply accept the default values, by hitting the enter key, for each question except for the fourth question entry point: (index.js) here you should type server.jsand then hit the enter key.

package name: (web-app-boilerplate)
version: (1.0.0)
description:
entry point: (index.js) server.js
test command:
git repository: (https://github.com/conor-deegan/web-app-boilerplate.git)
keywords:
author:
license: (ISC)

Once you have answered all of the questions you will be shown a sample of your package.json:

Hit the enter key one last time to confirm and create your package.json file. You should now see a second file in the left-hand menu above the README.md:

Create a server.js file

The repository will be structured as follows:

Where all of the React frontend code is inside the client directory, and all of the server related code is in the root directory. Our main server file will be called server.js and will be inside our root directory. To create this file run the following command in your VSCode terminal:

touch server.js

You will now see a server.js file in the root of your project directory, this is the primary entry point to the server.

React frontend boilerplate

We will use create-react-app to set the foundation for the React frontend. Create React App is a development environment for building a single-page application in React that handles a lot of the complexity for you. Under the hood, it uses Babel and webpack to compile and bundle your code.

To create our client directory and install the necessary packages for React we will use npx. Npx is a package runner tool that comes with npm, so it should already be installed on your computer. Run the following command in the terminal:

npx create-react-app client

This command will create a directory called ‘client’ in the root of your project which contains the React frontend.

Once complete, to confirm everything was installed correctly, we will start the React client. To do this we are going to create a start script in our package.json file.

Add the following to the "scripts" section of the package.json file in the root of your project directory:

"client": "cd client && npm start"

The scripts sections of your package.json file should now look something like:

You can run the following command in your terminal to start the front end client:

npm run client

This should launch a browser window at the path http://localhost:3000/ with the following:

You can quit this by hitting Crtl + C in your terminal window. That is it for the React frontend set-up (for now).

Node.js backend boilerplate

Create a .gitignore file

In order to avoid pushing certain files and folders to Github, you should add a .gitignore file to the root directory of your project by running:

touch .gitignore

Then place the following into your .gitignore file before saving it:

node_modules
package-lock.json
.env

This prevents pushing files and folders that are unnecessary to add to version control or files and folders which may contain sensitive information such as passwords and API keys.

Create a server

We will now focus on setting up our server. For this you will need to install a few dependencies:

  • express — a minimal/flexible Node.js web application framework.
  • body-parser — middleware for parsing incoming request bodies to JSON, available in the request object.
  • cors — a package for providing middleware that can be used to enable CORS with various options.

To install these, run the following command in the projects root directory:

npm install express body-parser cors

You should now see the following in the package.json file in the root directory of your project:

Next add the following code to your server.js file:

The comments should help explain exactly what is happening here.

  1. Import dependencies.
  2. Create an express instance named ‘app’.
  3. Configure some application-level middleware for our server.
  4. Set out server to listen on port 5000 or an environment variable if applicable.

Once you have added the code above, run the following command in your terminal in the root of the project directory:

node server

If everything was set up correctly you should see the following in your terminal:

Your server is now running on port 5000. Go ahead and navigate to http://localhost:5000/ in your browser, you should see the catch all response sent from the server.

You can now shutdown the server instance by hitting Crtl + C in your terminal window.

Frontend and backend communication

Great, you now have a React frontend application in the client folder, and a Node.js backend application in the root folder. Both can run, but independently and on different ports. We will now set up a protocol for communication between our frontend and backend applications.

Create a simple API

We will demonstrate this communication with a simple GET request that will return a string when called.

Run the following command in your terminal in the projects root directory:

mkdir routes && cd routes && touch routes.js && cd ..

Here we are creating a routes folder with a file routes.js inside of it.

Now run:

mkdir controllers && cd controllers && touch controllers.js && cd ..

Here we are creating a controllers folder with a file controllers.js inside of it.

Add the following code to controllers.js:

When called, this controller will respond to the client with a status code of 200 and a JSON object with our string ‘Hello from the server’.

Add the following code to routes.js:

In this routes.js file, we are creating an express router object named ‘router’ and creating a GET request route handler that will call our controller ‘saySomething’.

Add the following to line 26 of the server.js file:

// Require Routeconst api = require('./routes/routes');// Configure app to use routeapp.use('/api/v1/', api);

This imports and configures our app to use the routes that are defined in routes.js. This section of your server file should now look something like this:

Once you have added this to your server file, start the server again by running:

node server

Visit http://localhost:5000/api/v1/say-something in your browser. You should see the response from your server saying ‘Hello from the server’. Shutdown the server instance by hitting Crtl + C in your terminal window.

Call the API from the React Frontend

In order to make the API request from the client, we will use the HTTP client ‘axios’.

Axios is a Javascript library used to make HTTP requests from Node.js or XMLHttpRequests from the browser that also supports the ES6 Promise API.

Install axios by running the following command in your terminal:

cd client && npm install axios && cd ..

Next, delete the contents of your App.js file (client>src>App.js) and replace it with the following:

Here, we make a request using axios to our backend API (lines 11 -14) and display the response in the client (line 21).

Go ahead and start the React frontend application:

npm run client

Open your browser at http://localhost:3000/. Our hardcoded string ‘Hello from the frontend!’ is there however the response from the server does not seem to display.

If you inspect the request using your browser developer tools you will see that the request is being made to port 3000, however, our server runs on port 5000.

Request URL:http://localhost:3000/api/v1/say-something

One solution to this would be to update the value of the URL you are requesting using axios (line 11) to:

http://localhost:5000/api/v1/say-something

Although this will work, this is not a good solution as it would mean hardcoding the protocol (HTTP), host (localhost) and port (5000) directly into the request. If you ever wish to change the port your backend runs on you would need to update all of your axios requests. More importantly, when we build and host this web application in a production environment we will want to serve the static frontend files from the same host and port as the server (more on this later).

In order to solve this, we need to tell the frontend client to proxy any unknown requests to the server when in development. To do this, we need to add a proxy field to the bottom of our package.json file in the client folder:

"proxy": "http://localhost:5000"

Your client>package.json file should now look something like (don’t forget the trailing comma in the line above):

This way, when you call axios.get('/api/v1/say-something') in development, the frontend client will recognize that this is not a static asset, and will proxy the request to http://localhost:5000/api/v1/say-something as a fallback.

Now that this is in place, we need a way to start both the React client (on port 3000) and Node.js server (on port 5000) with the same command. Right now, if you were to start your React client with npm run client you will notice that our response string ‘Hello from the server’ does not appear and the following error is printed to your terminal:

Proxy error: Could not proxy request /api/v1/say-something from localhost:3000 to http://localhost:5000.
See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (ECONNREFUSED).

This is because, although our proxy worked, the port 5000 is currently closed.

To run both the client and the server at the same time we will make use of a package called concurrently. Another option would be to run the start command for the server and client in separate terminal windows, but this will save you that effort. Install concurrently by running the following command:

npm install concurrently

We will also use a package called nodemon. You may have noticed that when saving a file in create-react-app the development server automatically restarts and your changes appear in the browser window instantly. Nodemon provides the equivalent functionality for our server. It is a tool that helps in developing Node.js based applications by automatically restarting the server when file changes in the directory are detected.

Install nodemon with the following command:

npm install nodemon

Next, add the following two scripts to the scripts section of the package.json file in the root of your project directory:

"server": "nodemon server.js","dev": "concurrently --kill-others-on-fail \"npm run client\" \"npm run server\""

Here we are defining a script,server, that will run our server.js file using nodemon and another script, dev, that will run both our server script and client script at the same time.

The scripts section of your package.json file should now look like this:

We can now run npm run dev in our terminal window to start both our React frontend and Node.js backend at the same time.

Open your browser at http://localhost:3000/ and you should see the response from the API. You should also see a log of the API request printed in the terminal:

Request_Endpoint: GET /api/v1/say-something

This means that our React frontend called /api/v1/say-something using axios, the client then proxied this request from port 3000 to port 5000 and our server responded appropriately.

Shut down the web application by hitting Crl + C in your terminal window.

We now have a working sample API that demonstrates communication between the backend and frontend of our web application.

Preparation for deployment to production

Client preparation

In order to deploy your web application to a production environment, you will need to create a build (static html, css, and js files) of the React application. Create-react-app comes with the command npm run build which creates a build directory with this production build of your app.

We will add one more script to our package.json file in the root of our project directory:

"client:build": "cd client && npm run build"

Once you have added the above script to the package.json file, go ahead and run the following command in your terminal window:

npm run client:build

Once complete, you should see a new directory inside your client folder called ‘build’.

By default, create-react-app adds the build folder to your clients .gitignore file. We will need to remove this for now. Delete the line ‘/build’ from the .gitignore file in the client directory.

Delete the lines in yellow and save the file
Delete the lines in yellow and save the file
Delete the lines in yellow and save the file

Your client .gitignore file should now look something like this.

Your app is now ready to be deployed to a production environment.

Deployment to production

Commit your code to GitHub

At this point, you should push your changes to GitHub. There are a couple of ways you can do this. We will use the command line.

Start off by staging all of your changes by running the following command in your terminal window:

git add -A

Next, commit your changes by running:

git commit -m 'Initial commit to our app'

Finally, push your changes to GitHub by running:

git push

If all of this was completed successfully, you should now see your latest commit on GitHub.com:

Deploy your app to Heroku

Heroku is a cloud platform as a service (PaaS) that supports several programming languages, including Node.js. It runs apps on what it calls ‘dynos’ — which are really just virtual computers that can be powered up or down based on how big your application is and how much computing power is required. Heroku makes deploying and managing production-grade applications very simple at relatively low monthly costs (about $7/month), making it the perfect place for us to deploy our web app.

Start off by creating a Heroku account, choosing ‘Node.js’ as the primary development language.

Once you have created and verified your account, you should be able to begin setting up a new application from the Heroku dashboard (they also have a CLI):

Choose ‘Create new app’

Choose a unique name for your application and your application region and then click ‘Create App’:

We will now connect our Heroku app with our GitHub repository:

You can ignore the first section about adding the app to a pipeline, this is unnecessary and out of scope for this article.

Choose GitHub as your deployment method. If this is your first time using Heroku you will be required to connect your GitHub account by entering your GitHub username and password. Once connected, you should be able to search for your repository:

After connecting to your repository, you will be given the option to ‘Enable Automatic Deploys’ make sure to enable this feature. This is what will allow you to continuously push new code to your web app.

The last step is to simply click ‘Deploy Branch’. This will kick off a build process on Heroku. Once your app has been successfully built you will be able to view your app (don’t worry, the build process can take a few minutes).

Congratulations, you have now successfully built and deployed a production-grade web application 🥳

Pushing updates to your production application

As you continue to develop your app, you will want a way to deploy new code to production easily. Heroku makes this very straightforward.

Once you add new code to your app, simply run npm run client:build before you push the new code to Github (note that this is not necessary for server-side code). Heroku will automatically rebuild your application once new code is committed to the master branch on GitHub.

Let’s see this in action. In client>src>App.js, change the hardcoded string “Hello from the frontend!” to “Here is our new feature!”. Save the file and run the following command in your terminal window:

npm run client:build

This will create a new production build of your application containing the new string. Once the build as completed, stage your changes by running:

git add -A

Next, commit your changes by running:

git commit -m 'A new feature'

Finally, push your changes to GitHub by running:

git push

Once you have done this, you should see that a new build has been triggered in the “Activity” tab of the Heroku dashboard. After a minute or two refresh your application and you will see the new string in the browser window.

Deploying new code to your application is as simple as pushing your code to GitHub.

That’s a wrap

You should now have a solid foundation for a production-grade web application.

If you have any questions at all, ask me here. The completed repository can be found here. Thanks for reading 🤘

Weekly Webtips

Explore the world of web technologies through a series of tutorials

Sign up for 💌 Weekly Newsletter

By Weekly Webtips

Get the latest news on the world of web technologies with a series of tutorial Take a look.

By signing up, you will create a Medium account if you don’t already have one. Review our Privacy Policy for more information about our privacy practices.

Check your inbox
Medium sent you an email at to complete your subscription.

Conor Deegan

Written by

Software Engineer 👨‍💻 JavaScript (Node & React) 🤟 Cloud (AWS) ☁️

Weekly Webtips

Explore the world of web technologies through a series of tutorials

Conor Deegan

Written by

Software Engineer 👨‍💻 JavaScript (Node & React) 🤟 Cloud (AWS) ☁️

Weekly Webtips

Explore the world of web technologies through a series of tutorials

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store