How to deploy React + Node.js application to Heroku
Tags: react, javascript, beginners, node
Published: 2020-07-07 13:36:34


In this article, we will explore, Step by step instructions for deploying React + Node.js app to Heroku which we created in my previous article [HERE](https://dev.to/myogeshchavan97/build-an-amazing-job-search-app-using-react-42p)


**Let's get started**

Clone the repository code from [HERE](https://github.com/myogeshchavan97/github-jobs-react-app
)

To run the application, execute following commands

In first terminal

```js
1. yarn install
2. yarn start
```

In another terminal

```js
1. cd server
2. yarn install
3. yarn start
```
<BR />
Once both the servers are started, you can access the application at http://localhost:3000/


Now, let's start with steps to deploy to Heroku.


Heroku requires, the application to have a `start` script.

Open `server/package.json` and check if we have a script with name `start` in `package.json` file

```js
"start": "nodemon server.js"
```

`Nodemon` is good when we are developing on local environment but on Heroku, we don't need `nodemon` but just node is required. 

So remove `nodemon` entry from `dependencies` section and change script from 

```js
"start": "nodemon server.js"
```

to

```js
"start": "node server.js"
```

Now, your ``package.json`` will look like this

```js
{
  "name": "server",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "scripts": {
    "start": "node server.js"
  },
  "dependencies": {
    "axios": "0.19.2",
    "cors": "2.8.5",
    "express": "4.17.1"
  }
}
```

By default, Heroku runs our Node.js application on some randomly available port which is stored in `process.env.PORT` variable. So we need to make sure, when we start the server we are using  that environment variable. 

We have already added the code for it in our `server.js` file

```js
const PORT = process.env.PORT || 5000;
```

which says take the port value from `process.env.PORT` environment variable and if the environment variable with name `PORT` does not exist then use default value of `5000`.

Then we are starting our server by accessing the variable `PORT`

```js
app.listen(PORT, () => {
  console.log(`server started on port ${PORT}`);
});
```

Now, open main `package.json` and change

```js
"scripts": {
  "start": "react-scripts start",
  "build": "react-scripts build",
  "test": "react-scripts test",
  "eject": "react-scripts eject"
}
```

to

```js
"scripts": {
  "start-client": "react-scripts start",
  "build": "react-scripts build && (cd server && yarn install)",
  "test": "react-scripts test",
  "eject": "react-scripts eject",
  "start": "cd server && yarn start"
}
```

Here, we have done following changes
1. Changed the script name from `start` to `start-client` 
2. Changed `build` command
3. Added new `start` script to start the Node.js server

The reason for specifying `yarn install` in build command is that, Heroku will run this command while building the app so before running `start` command, `node_modules` folder will be available


Now, open `src/utils/constants.js` and change


```js
export const BASE_API_URL = 'http://localhost:5000';
```

to

```js
export const BASE_API_URL = '';
```

Now, stop both the servers which we started initially by running `yarn start` command. 


Now, run the `yarn build` command which will execute the following command

```js
react-scripts build && (cd server && yarn install)
```

Now, once the command is executed successfully, run the `start` script

```js
yarn start
```

which will execute the following command
```js
cd server && yarn start
```

Now, you can access the application by visiting http://localhost:5000/
and your Node.js API will also be accessible on the same port 5000 at http://localhost:5000/jobs

The reason for React and Node.js application running on the same port is because when we run the `yarn build` command, it creates a `build` folder in our project which contains all the code of our React application and in `server/server.js` file, we have the following code

```js
const buildPath = path.join(__dirname, '..', 'build');
app.use(express.static(buildPath));
```

This code will take the contents of `build` folder and If the 'build' folder contains `.html` file, then `Express` server will render the contents of that file when we access http://localhost:5000/.

And our Node.js APIs are already available on Port `5000` so both the applications are running on same port and therefore we don't need to execute two separate commands in separate terminals to start the React App and  Node.js application.

So now there is no need of using `cors` npm module to add as a middleware in `server.js`

```js
app.use(cors());
```

This was only required because previously our React application was running on port 3000 and Node.js application was running on Port 5000 and browser does not alllow accessing data from different ports because of `Cross-origin resource sharing (CORS)` policy. So to allow our Node.js server accept requests from any client, we added the `cors` package.

But its not required now. So remove the `cors` package from `server/package.json` file. 

Your updated `package.json` will look like this now

```js
{
  "name": "server",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "scripts": {
    "start": "node server.js"
  },
  "dependencies": {
    "axios": "0.19.2",
    "express": "4.17.1"
  }
}
```

Also remove the import for `cors` in `server.js` file and its use.

```js
const cors = require('cors');
app.use(cors());
```

So your final `server.js` file will look like this

```js
const path = require('path');
const axios = require('axios');
const express = require('express');
const app = express();

const PORT = process.env.PORT || 5000;

const buildPath = path.join(__dirname, '..', 'build');
app.use(express.static(buildPath));

app.get('/jobs', async (req, res) => {
  try {
    let { description = '', full_time, location = '', page = 1 } = req.query;

    description = description ? encodeURIComponent(description) : '';
    location = location ? encodeURIComponent(location) : '';
    full_time = full_time === 'true' ? '&full_time=true' : '';
    if (page) {
      page = parseInt(page);
      page = isNaN(page) ? '' : `&page=${page}`;
    }
    const query = `https://jobs.github.com/positions.json?description=${description}&location=${location}${full_time}${page}`;
    const result = await axios.get(query);
    res.send(result.data);
  } catch (error) {
    res.status(400).send('Error while getting list of jobs.Try again later.');
  }
});

app.listen(PORT, () => {
  console.log(`server started on port ${PORT}`);
});
```

Now, we're done with the code changes. 

Create a new repository in GitHub and let's push the changes to Github

**Add all changes to staging area**

```js
git add --all .
```

**Commit the changes**

```js
git commit -m "Changes for heroku"
```

**Push the changes to github**

```js
git push origin master
```

Now, let's deploy the application to Heroku.


* Login to your Heroku account and navigate to dashboard [HERE](https://dashboard.heroku.com/)

* Click on the New button from top right section and select `Create new app` option

![New Button](https://gist.github.com/myogeshchavan97/e0be7fc4c838544e2d00afeb3a82ae10/raw/1078acc5103171ab91da1836eddfb2ba08dcd592/new_button.png)

* Provide the name for the App and click on `create app` button
  
![Create App](https://gist.github.com/myogeshchavan97/e0be7fc4c838544e2d00afeb3a82ae10/raw/19d64691355a36e468b845badbb80dc81600c30c/create_app.png)

* Click on `Connect to GitHub` Link under deployment method section
  
![Connect to GitHub](https://gist.github.com/myogeshchavan97/e0be7fc4c838544e2d00afeb3a82ae10/raw/2ebb615f879b6ad45513b055bbc1688b9026312f/connect.png)

* Enter name of your GitHub repository and click on `Search` button

![Select Repository](https://gist.github.com/myogeshchavan97/e0be7fc4c838544e2d00afeb3a82ae10/raw/c540f07e88947ce0ca9272102e2444e52e19962e/select_repo.png)

* Click on the `Connect` button to connect the repository to Heroku
  
![Connect Repository](https://gist.github.com/myogeshchavan97/e0be7fc4c838544e2d00afeb3a82ae10/raw/6a6d8920a980543d4ac347d58db300630f28fca8/connect_btn.png)

* Select the `branch` to deploy (It's master in our case) and click on `Deploy Branch` button

![Deploy Branch](https://gist.github.com/myogeshchavan97/e0be7fc4c838544e2d00afeb3a82ae10/raw/0425b648cd3bb75fa2c5bcdd79692dd202faf21e/select_branch.png)

* Now, your deployment will start

![Deployment](https://gist.github.com/myogeshchavan97/e0be7fc4c838544e2d00afeb3a82ae10/raw/ec979ea19935b8511404d801dd33836995d88832/deployment.png)

* Once it's completed, You will see a success message along with the option to view your deployed App

![Deployment Success](https://gist.github.com/myogeshchavan97/e0be7fc4c838544e2d00afeb3a82ae10/raw/fbe8c3a6fb4cc384ca82b4a0678cb462adc3de52/success_msg.png)

-------------

You can find the complete GitHub source code for this article [HERE](https://github.com/myogeshchavan97/github-jobs-react-app-heroku) and live demo of the App deployed on Heroku [HERE](https://github-jobs-react-app.herokuapp.com/)

**Note:** For Heroku, If you're using a free account, then your application will sleep after 30 minutes of inactivity and once new request comes, the application will start again so it might take some time to load the application.


**Don't forget to subscribe to get my weekly newsletter with amazing tips, tricks and articles directly in your inbox [here](https://yogeshchavan.dev).**

[<img src="https://cdn.buymeacoffee.com/buttons/default-yellow.png" >](https://www.buymeacoffee.com/myogeshchavan97)