Deploying Nx workspace based Angular and NestJS apps to Heroku
Tags: angular, nestjs, heroku, deploy
Published: 2021-06-25 10:37:49


In previous articles, I've shown you how to create an Nx Workspace with Angular and NestJS applications in it. After the applications are ready, we need to host them somewhere. [Heroku](www.heroku.com) is one of the services that lets us deploy applications easily. In this article, I'll demonstrate how to deploy the Angular and NestJS applications that are developed using an Nx monorepo. You can find the example code with the aforementioned applications in my [GitHub repository](https://github.com/ktrz/nx-photos/tree/nxDeployHeroku_entryPoint). To follow this article, please **fork** this repo, clone it locally and checkout `nxDeployHeroku_entryPoint`.

```shell
git clone git@github.com:<your_username>/nx-photos.git

# Or using Https
git clone https://github.com/<your_username>/nx-photos.git

cd nx-photos

git checkout nxDeployHeroku_entryPoint
```

## Install Heroku CLI

To follow this article, you need to have the Heroku CLI installed. Please follow the official installation instruction on the Heroku documentation page [here](https://devcenter.heroku.com/articles/heroku-cli).
After you install the CLI, type the following command to log in to Heroku:

```shell
heroku login
```

## Deploying NestJS app

We're going to start with deploying the NestJS application. The first thing we need to do is creating a Heroku application. Because you need to come up with a unique application name in all the examples, I'll be using `ktrz-` prefix for the app names. Please replace it with your own prefix so that the application names don't collide with each other.

To create a Heroku application we can use the following command:

```shell
heroku create -a ktrz-nx-photos-api
```

Now we need to configure the application to use Node for building the application. This is what buildpacks are for. To add a buildpack, the `heroku buildpacks:add` command can be used:

```shell
heroku buildpacks:add -a ktrz-nx-photos-api heroku/nodejs
```

Heroku uses a `Procfile` file to specify the commands that are executed on application startup. The default configuration allows for only one *Procfile* and it has to be in the repository root. For it to work with the monorepo with multiple applications, we need a way to configure multiple *Procfiles* in the repository. For this purpose, a `multi-procfile` buildpack can be used. We can add it using a similar command to the previous one:

```shell
heroku buildpacks:add -a ktrz-nx-photos-api heroku-community/multi-procfile
```

Now we can create a *Procfile* and place it in the directory that makes sense for the monorepo. Let's create the following file: 

```
web: node dist/apps/photo/api/main.js
```
`apps/photo/api/Procfile`

To let the buildpack know about the location of the *Procfile*, we need to set `PROCFILE` env variable for the Heroku application. We can do it using the following command:

```shell
heroku config:set -a ktrz-nx-photos-api PROCFILE=apps/photo/api/Procfile
```

By default, Heroku uses the `build` script from the `package.json` file to build the application. We need a more customizable way of building an application so we can configure which application in a monorepo to build. By defining a `heroku-postbuild` script, we tell Heroku to not use a default `build` one and use our custom script instead. Let's create the following script:

```json
scripts: {
  "heroku-postbuild": "nx build $PROJECT_NAME --prod"
}
```
`package.json`

As you can see, the `PROJECT_NAME` env variable is used to determine which application to build. It needs to be configured on the Heroku environment:

```shell
heroku config:set -a ktrz-nx-photos-api PROJECT_NAME=photo-api
```

What is left to do is push the changes to a branch and configure Heroku app to use the repository as a source for deployment:

```shell
git checkout -b nx-photo-deploy

git push -u origin photo-api-deploy
```

To configure the Heroku app, go to the [dashboard](https://dashboard.heroku.com/apps) and choose the application that you've created before:

![Heroku Dashboard](//images.ctfassets.net/zojzzdop0fzx/2tNGW0zCi6w1BxLmFKMOgo/8374abd3ee82579aa77c0346e7626a48/heroku-dashboard.png)

Next, navigate to the `Deploy` tab, choose the GitHub method, search for your repository, and click `Connect`:

![Heroku d](//images.ctfassets.net/zojzzdop0fzx/dKrIDngaBYp4gNs3eysbX/f50e2c283178d5a84ad3056e3925a3d7/heroku-deploy.png)

Finally, on the bottom, you can choose to deploy manually from the branch that you've created a moment ago:

![Heroku Manual Deploy](//images.ctfassets.net/zojzzdop0fzx/3QUFwFBJR8FTy2YLE467JW/264b0080330c3252099bc44e4f171b3e/heroku-manual-deploy.png)

- in package.json add script: 

```json
scripts: {
  "heroku-postbuild": "nx build $PROJECT_NAME --prod"
}
```
`package.json`

```shell
heroku create -a ktrz-nx-photos-api
heroku config:set -a ktrz-nx-photos-api PROJECT_NAME=photo-api

heroku buildpacks:add -a ktrz-nx-photos-api heroku/nodejs
heroku buildpacks:add -a ktrz-nx-photos-api heroku-community/multi-procfile

# create `apps/photo/api/Procfile` file
heroku config:set -a ktrz-nx-photos-api PROCFILE=apps/photo/api/Procfile
```

To learn more about *heroku-buildpack-nodejs* and *heroku-buildpack-multi-procfile* configuration, please visit the official documentation:
- [heroku-buildpack-nodejs](https://elements.heroku.com/buildpacks/heroku/heroku-buildpack-nodejs)
- [heroku-buildpack-multi-procfile](https://elements.heroku.com/buildpacks/heroku/heroku-buildpack-multi-procfile)

## Deploying Angular app

Deploying an Angular app has a lot of similar steps. 

```shell
# create another Heroku app
heroku create -a ktrz-nx-photos-fe

# add same buildpacks
heroku buildpacks:add -a ktrz-nx-photos-fe heroku/nodejs
heroku buildpacks:add -a ktrz-nx-photos-fe heroku-community/multi-procfile

# configure Procfile
heroku config:set -a ktrz-nx-photos-fe PROCFILE=apps/photo/fe/Procfile

# set PROJECT_NAME env variable
heroku config:set -a ktrz-nx-photos-fe PROJECT_NAME=photo-fe
```

The Angular application can be served as just static files with routing configured to always point to the root `index.html` and let Angular handle the rest. We can use another buildpack to accomplish that.

```shell
heroku buildpacks:add -a ktrz-nx-photos-fe heroku-community/static
```

*heroku-buildpack-static* is configured via `static.json` file. We can do a basic configuration like so:

```json
{
  "root": "dist/apps/photo/fe/",
  "routes": {
    "/**/*.html": "index.html"
  }
}
```
`static.json`

The example Angular application is configured to use `/api` proxy for the backend. This also can be configured within *static.json* file:

```json
{
  "proxies": {
    "/api/": {
      "origin": "https://ktrz-nx-photos-api.herokuapp.com/api/"
    }
  }
}
```
`static.json`

The last thing to do is configure Heroku to use the static buildpack via the Procfile:

```
web: bin/boot
```
`apps/photo/fe/Procfile`

To learn more about *heroku-buildpack-static* configuration, please visit the oficial documentation [here](https://elements.heroku.com/buildpacks/heroku/heroku-buildpack-static).

Let's commit the changes and configure the second app to use the same GitHub repository:
- Go to [dashboard](https://dashboard.heroku.com/apps) and choose the frontend application that you've created before. 
- Next, navigate to the `Deploy` tab, choose GitHub method, search for your repository, and click `Connect`.
- Finally, on the bottom you can choose to deploy manually from the branch that you've pushed to a moment ago.

After all those steps, you can navigate to your deployed app:

![Open app](//images.ctfassets.net/zojzzdop0fzx/13suoRUnSE889N7M5p3B6r/cf4d6a0d6a2d890fcf389dd85135a35a/heroku-open-app.png)

## Summary

If you want to see the result code, you can find it on my [GitHub repository](https://github.com/ktrz/nx-photos/tree/post/nx-deploy-heroku).

In case you have any questions, you can always tweet or DM me [@ktrz](https://twitter.com/ktrz__). I'm always happy to help!

---

_This Dot Labs is a modern web consultancy focused on helping companies realize their digital transformation efforts. For expert architectural guidance, training, or consulting in React, Angular, Vue, Web Components, GraphQL, Node, Bazel, or Polymer, visit [thisdotlabs.com](https://www.thisdotlabs.com)._

_This Dot Media is focused on creating an inclusive and educational web for all. We keep you up to date with advancements in the modern web through events, podcasts, and free content. To learn, visit [thisdot.co](https://www.thisdot.co)._