How to deploy a MEN stack app from our local machines to Heroku
Tags: deployment, heroku, node, beginners
Published: 2020-05-30 13:28:03

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/o4y8e4m1k38i5wzw6pk0.jpeg)

## Introduction
Recently when I deployed a web application on Heroku, I spent a lot of time debugging and researching. A seemingly simple process turned into a few hours task. Hence, I would like to share my experience.

In this article, I will describe how to deploy an existing web application that is built using MongoDB, Express.js and Node.js from our local machines to Heroku. 

## Prerequisites
You'll need to have:
* __An existing MEN stack app__
* __Git installed__. Read [this guide] (https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) if you need to install Git. Learn about how to set up Git [here](https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup)
* __Heroku Command Line Interface (CLI) installed__. This CLI will make it easier to create and manage your Heroku apps directly from the terminal. The simplest way to install it on macOS machines is using brew.
 
```bash
brew tap heroku/brew && brew install heroku
```
For other operating systems, please refer to [here](https://devcenter.heroku.com/articles/heroku-cli#download-and-install)
After you go through the installation process, you can check if the CLI has installed correctly by running:

```bash
heroku --version
```
If it has been installed successfully, you should see `heroku/x.y.z` (x, y, z are numbers) in the output. 

* __You will also need an account at Heroku website__.

## 1. Configure package.JSON

We need to check if package.JSON has all the __correct dependencies__, as Heroku will need the list to know what to install for the app to work. Then modify the file by __adding the following script__. This will tell Heroku how to start the app.

```json
"scripts": {
		"start": "node server.js",
		[...]
	}
```
## 2. Using process.env.PORT 

When we test our Express.js app in the local environment, it is usually configured to bind to a port instead of the one provided by Heroku via the __`$PORT` environment variable__. For example in app.js file,

```node.js
app.listen(3000, function (){
  console.log("App is listening on port 3000");
});
```

However, When Heroku's port for the app to bind to is __dynamic__, its value is __exposed in the `$PORT` env var__. __To make sure our app bind to this port instead, we need to change our code to:__

```node.js
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Our app is running on port ${PORT}`);
});
```

By using this code, the app will use the `$PORT` env var if available or fallback to a default port 3000 if we are running locally.

## 3. Connecting with Database using MongoDB Atlas

I am going to use __[mongoDB Atlas](https://www.mongodb.com/cloud/atlas)__ to host the database of our application on the cloud.

After registering, we can login and create a new database cluster.
If you want a free option, make sure __'FREE TIER AVAILABLE'__ options are selected and it says __FREE__ on the bottom-left corner, before clicking the green button to create our cluster.
 
After the cluster is created (which would take some time), we can __click CONNECT button__. 

Then we need to paste __0.0.0.0/0__ for IP address and click the green "Add IP Address" button. This will enable access to our database server from any IP.

Create a user by entering a new username and a strong password. Make sure to __remember our credentials__ as we would need that for our SRV address later. Press the "Create MongoDB User" button. 

After this is done, we can press the "Choose a connection method" button on the bottom right.

Click the __"Connect Your Application"__ button in the next window.

Choose the __"Short SRV connection string"__ and click __COPY__ button.

In the SRV address we need to replace PASSWORD with the password we chose when we created a user. Then remember to save the address somewhere for later usage.

## 4. Login to Heroku

You can login to Heroku using the Heroku CLI. If you would like to login through the web browser, use the following command in the terminal.

```bash
heroku login
```
If you want to log in through the command line instead, add the -i flag.

```bash
heroku login -i
```
## 5. Initialise a Git repository, add and commit files to Git

When we are in the project folder, initialise a new Git repository (if we have not done it) by using the following command in the terminal.

This step is __very important__ because __Heroku relies on Git__ for deploying app from our local machine to its cloud servers. 

```bash 
git init
```
Afterwards, follow the following steps to add and commit files to Git.

```bash
git status
```

```bash
git add .
```

```bash
git commit -m "<your-commit-message>"
```
## 6. Create a new Heroku project

Now, we can create a new Heroku project with a name we choose. I name mine as `demo_app`. 
* If we don't name our project, Heroku will create a random name for our project. 
* The name will form part of the URL which can be used to access our project. It means we need to choose a special name for our project that no one has used.
* It is possible to rename our project later so don't need to worry too much. Read [here](https://devcenter.heroku.com/articles/renaming-apps) for more details. 

```bash
heroku create demo_app
```


## 7. Setting up environment variables for database URL
At the moment one database is shared between development and production environments. This is not good practise because if we lose any data in our development environment, the same data will be lost in production. We also do not want to expose sensitive data such as MongoDB Atlas SRV address on Github. 

To prevent these issues, we need to set up __environmental variables of DATABASEURL locally and on Heroku__.

To set up DATABASEURL locally to localhost, run the following script on the terminal. Remember to plug in name of your app folder in the URL. 

```bash
export DATABASEURL=mongodb://localhost:27017/<name_of_your_app_folder>
```

Add the following after variable declaration in app.js file. `process.env` is the way Node.js used to access environment variable. Then start the server to see if the correct localhost URL appears in the output on terminal. 

```node.js
console.log(process.env.DATABASEURL)
```
If the correct URL appears, modify mongoose.connect script in app.js file to the following. This allows localhost acts as a backup if something goes wrong with the environment variable. 

```node.js
var url = process.env.DATABASEURL || "mongodb://localhost:27017/<name_of_your_app_folder>"
mongoose.connect(url, { useNewUrlParser: true }); 
```

To set up a separate DATABASEURL for Heroku, go to our application settings after we logged in Heroku on web browser. 

Scroll down to __Config Vars__ section and click __Reveal Config Vars__ button.

Enter __DATABASEURL as key__ and your __MongoDB Atlas SRV address as value__. Then click Add.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/y5xmti5s060d94canzw0.png)

## 8. Add and commit files to Git and push to Heroku

Before we deploy to Heroku, make sure we have Git added all the relevant files and committed them.

```bash
git add .
git commit -m "ready to deploy"
```

The final step is to push to our Heroku master branch.

```bash
git push heroku master
```
We should see a bunch of information prints out in the terminal as Heroku builds and deploys our app.

If `Verifying deploy...done` appears, it means our build was successful.

Congratulations! Now you app is hosted on your-project-name.herokuapp.com for all to visit! 

If there is "application error" appears when you visit your app, I would recommend checking logs with the following command and referencing [Heroku docs](https://devcenter.heroku.com/articles/git).

```bash
heroku logs
```
Thanks for reading! I hope this article is helpful. 

<a href="https://www.buymeacoffee.com/phyllisyymo" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/default-orange.png" alt="Buy Me A Coffee" height="41" width="174"></a>