Deploy an Nx Workspace to Heroku

How to Deploy an Angular and NestJS Full-Stack Web Application from a Nrwl Nx Workspace to Heroku

7 min readMar 30, 2020

--

In this article, I’ll show you how to deploy a basic full-stack web application from an Nx workspace to Heroku in eight main steps:

  1. Create an Nx Workspace
  2. Modify app.module.ts in the Backend to Statically Serve the Angular Frontend
  3. Change port to PORT in the main.ts file in the Backend
  4. Build the Frontend and Backend
  5. Modify package.json to (a) Specify Engines and (b) Run the Backend in the start Script
  6. Modify the .gitignore File to Commit and Push Our /dist Folder
  7. Create a Procfile for Heroku
  8. Point to Heroku and Deploy

Before we start, I’ll state some of my assumptions:

Finally, you can view the example built in this article on GitHub. Now, let’s get started.

(1) Create an Nx Workspace

Using the command line, navigate to the directory where you’d like to store your workspace and run:

npm init nx-workspace nx2heroku

where nx2heroku is the name of the workspace that you want to create. The generation process will prompt you to answer four questions:

  1. “What to create in the new workspace?” We’ll select angular-nest to build a full-stack application containing an Angular frontend and a NestJS backend.
  2. “Application name?” I’ll use nx-app for this example. The name that you enter here will be the name of your frontend application.
  3. “Default stylesheet format?” I’ll choose CSS for this example, but you can choose whichever option you prefer.
  4. Finally, we’ll be prompted to say whether we’d like to send analytics information to Google. Select whichever option you prefer.

NPM will now generate our Nx workspace. When it’s finished, your new directory should look like the one shown in Figure 1.

Directory Structure of the New Nx Workspace
Figure 1 Directory Structure of the nx2heroku Workspace

(2) Modify app.module.ts in the Backend to Statically Serve the Angular Frontend

We want our API (i.e., our backend) to statically serve our Angular frontend when users visit our application online. NestJS provides a package that will help us do this, but we have to manually install it. In the command line, type:

npm install --save @nestjs/serve-static

to install the serve-static package.

Next, open the app.module.ts file located in /apps/api/src/app. Here, we’ll tell our NestJS backend to statically serve our Angular frontend when users visit our application. Take a look at the Gist in Figure 2 below to see how this file is modified.

Figure 2 The modified app.module.ts file in /apps/api/src/app.

We’ve added two import statements: one for the ServeStaticModule and one for join. Then, we added an import to the imports metadata property on the @Module decorator. This tells NestJS to statically serve the Angular frontend, which is named nx-app. This will become clearer later, but we’re actually serving the production build of our nx-app frontend that will be located in /dist/apps later.

(3) Change “port” to “PORT” in the main.ts File in the Backend

The production version of our application must allow Heroku to set the port at which our web server will listen for connections from users. To do this, our API (i.e., NestJS backend) should listen to the PORT variable set in the Heroku configuration environment. Currently, our API listens to process.env.port, but this needs to be process.env.PORT.

Let’s open the main.ts file located in /apps/api/src. Change the reference to process.env.port to process.env.PORT. This change should be located on line 14. Although it’s optional, you could also change the console.log() on line 16 to simply refer to the port on which the app is listening. See Figure 3 below for the complete, modified main.ts file.

Figure 3 Changing “port” to “PORT” in the main.ts File

(4) Build the Frontend and Backend

Now that we’ve made our changes to the backend source files, let’s build the frontend and backend. In the command line, run both of the following commands:

  1. ng build --prod api to build the backend API (i.e., NestJS).
  2. ng build --prod nx-app to build the frontend (i.e., Angular SPA).

Production builds of our frontend and backend are now located in the /dist/apps folder of our workspace. Your /dist folder should look like that shown in Figure 4.

Figure 4 The /dist Folder Containing Production Builds of the Frontend and Backend

(5) Modify package.json to (a) Specify Engines and (b) Run the Backend in the “start” Script

Heroku needs to know (a) what version of Node our application runs on and (b) how to start our application (i.e., which file it should execute to start the application).

(a) Specify the Engines

First, we need to know which version of Node we’re running. We do this by entering the following command into the command line:

node --version

We should see a response like v10.14.2. Let’s make note of our version.

Now, we’ll open the package.json file and add the property "engines" with a value of {"node" : "10.x"}, where “10.x” is your version of Node. Your package.json should now look something like this below:

{
"name" : "nx2heroku",
"version" : "0.0.0",
"license" : "MIT",
"engines" : {
"node" : "10.x"
},
"scripts" : {
...
}
...
}

(b) Run the Backend in the “start” Script

Heroku will run the start script located in our package.json file to start our application on deployment. We want Heroku to execute our API (i.e., NestJS backend) to start our application. Right now, though, the package.json file tells Heroku to run ng serve as the start script. Let’s change this.

Open the package.json file located in the root of our workspace. Under scripts: you should see the key start. Change ng serve to:

node dist/apps/api/main

This tells Heroku to execute the main.ts file from the production build of our backend.

While we’re in the package.json file, we can also remove the build script. When we deploy to Heroku, Heroku will run the build script in our package.json file. Since we’ve built our frontend and backend locally, though, we don’t need Heroku to do this. By removing the build script, we let Heroku skip the build process.

(6) Modify the .gitignore File to Commit and Push our /dist Folder

The .gitignore file in the root of our workspace tells Git to ignore our /dist folder, which is where our production builds of our frontend and backend are located. We want to push this folder to Heroku, though, so we need to remove or “comment-out” the entry for /dist in the .gitignore file.

Open .gitignore in the root of the workspace. Remove the line that says /dist. Now, Git will commit and push this folder to Heroku.

While we’re here, we can also add a line to ignore the /apps folder, because we are building our frontend and backend locally before deploying. Thus, Heroku doesn’t need the source code files.

(7) Create a Procfile for Heroku

Heroku will look for a Procfile in the root directory to determine what type of process to start and how to start it. So, in the root of our workspace, let’s create a file named Procfile (with capital P and no extension). Open this new file and enter the following line:

web: npm run start

This tells Heroku to start a web process and execute the start script from our package.json file to start our application. As you’ll recall, our start script says to execute the main.js file of our backend. So, we’re essentially telling Heroku to start our application by running our NestJS backend. And, since our backend is configured to statically serve our Angular frontend, a user who visits our app will receive the Angular frontend in response.

(8) Finally: Point to Heroku and Deploy!

Now, we deploy our app to Heroku. I assume that you’ve created an app from your Heroku dashboard. (If not, go to your Heroku dashboard and create a new application, which essentially creates a place for you to deploy your application to.)

First, we need to point git to our remote app on Heroku. We do this by entering the following command in the command line (you must have the Heroku CLI installed):

heroku git:remote -a nx-app

where nx-app is the name of the application on Heroku. Next, we need to stage and commit our workspace in git. We do this by running the following commands:

  1. git add . to stage the workspace.
  2. git commit -m 'changes for deployment to Heroku' to commit the changes.

Finally, deploy your application to Heroku by running:

git push heroku master

Heroku will build and start your application.

Now, you should be able to open the app in a web browser and see it running live on Heroku. You should see something like what’s shown below in Figure 5. Congratulations! You’ve deployed a full-stack application in an Nx workspace to Heroku.

Again, you can find the source files for this example on GitHub.

Figure 5 The Live Application on Heroku

--

--

Building Scaffld | MA, University of Chicago | Interests: Software Engineering, Social Science, Writing, Politics, Education