Deploying to Heroku
Published: 2021-04-16 14:50:43

Deploying to Heroku is not so difficult but the setup might b confusing if you haven't done such a thing before. Start out by [creating an account](https://signup.heroku.com/) and installing the [Heroku CLI](https://devcenter.heroku.com/articles/heroku-cli). You can mainly follow the instructions in _[Deploying Spring Boot Applications to Heroku](https://devcenter.heroku.com/articles/deploying-spring-boot-apps-to-heroku)_ but with some differences:
- No need to create a Spring application if you already have one.
- If you already have a git repo as well you can skip ahead to the heroku commands. Make sure you are logged in with the Heroku CLI:
```
heroku login
```

Then create the heroku application:

```bash
heroku create
```
Before you push it however, you should add the database addon for your app
```
heroku addons:create heroku-postgresql
```
This will add a database to your Heroku app which doesn't require any setup. Although you still have to set the database properties in `application.properties`. Heroku will provide the database url, database user and database password in three environment variables `SPRING_DATASOURCE_URL`, `SPRING_DATASOURCE_USERNAME`, and `SPRING_DATASOURCE_PASSWORD` which we can use in our production environment.

### Setting up Production & Development Properties
Create a file called `application-production.properties` in `src/main/resources`:

```properties
# src/main/resources/application-production.properties

spring.jpa.database=POSTGRESQL
spring.datasource.platform=postgres

# Here is where we use the three environment variables which will replace whatever value was set in the default application.properties
spring.datasource.url={SPRING_DATASOURCE_URL}
spring.datasource.username={SPRING_DATASOURCE_URL}
spring.datasource.password={SPRING_DATASOURCE_PASSWORD}

spring.jpa.show-sql=true
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
```
Add and commit the changes and then push the application to the Heroku repo:
```bash
git push heroku master
```
**Note:** _If `master` doesn't work, try `main`._

After the Heroku build process, your backend application should be ready to serve requests. You can either click the link shown in the terminal or write `heroku open` to open the application web page.

## Frontend Deployment
For the frontend, the deployment process is a bit different. Start out by creating a git repo (`git init .`) where you have the root of your frontend. In the skeleton application that would be `frontend`. 

### Dependencies
We need to add some dependencies to the `package.json` which will be for our production server

```json
# frontend/package.json

{
  ...
  "dependencies": {
    ...
    "express": "^4.17.1",  # A node server module
    "path": "^0.12.7"      # For working with file and directories
  }
  ...
}
```
**Note:** _JSON doesn't support comments so you should only include the dependency values and not the text with '#'._

### Server Script
Now you can go ahead and create our script that will setup and run the express server. Create a file called `server.js` with the following content:
```js
// frontend/server.js

const express = require('express');
const path = require('path');
const port = process.env.PORT || 80;
const app = express();
// the __dirname is the current directory from where the script is running
app.use(express.static(__dirname));
app.use(express.static(path.join(__dirname, 'build')));
app.get('/ping', function (req, res) {
    return res.send('pong');
});
app.get('/*', function (req, res) {
    res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
app.listen(port);
```
**Note:** _It is not part of our actual frontend source code so it is placed directly inside `frontend` folder and **not** in `frontend/src`._

### Procfile
Heroku by default uses `npm start` to run the application but the `npm start` command runs a development version which is not optimized for production usage (it's slower due to development features like auto-reload). To make Heroku use a different command we need to add a so called Procfile. When Heroku sees the existence of this file, it will run whatever command is written in the Procfile. Create the file (simply named `Procfile` in `frontend` folder) with the following:
```procfile
web: node server.js
```
**Note:** _`web` specifies that it is a web process. You can read more [here](https://devcenter.heroku.com/articles/procfile)._

### Production/Development URL
Finally we need to make sure that the frontend is making requests to the correct URL based on wether we are in production (your app URL) or in development (localhost). Update the `frontend/src/api/Api.js` file with the following:
```javascript
const production  = '<YOUR BACKEND APP URL GOES HERE>';
const development = 'http://localhost:8080';
const BASE_URL = (process.env.NODE_ENV ? production : development);
```

That should be it! Add and commit the **frontend** git project and run the Heroku commands:
```
heroku create
```
```
git push heroku master
```
```
heroku open
```
You should now have a frontend and a backend running with the frontend connecting to the backend. If there are any errors in the Heroku build you can use `heroku logs --tail` to get the application logs. You can also (when logged in) use the [Heroku dashboard](https://dashboard.heroku.com/apps) to get an overview of your apps, change their settings, see the environment variables or the logs.