Deploy an Nx Workspace to Heroku
How to Deploy an Angular and NestJS Full-Stack Web Application from a Nrwl Nx Workspace to Heroku
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:
- Create an Nx Workspace
- Modify
app.module.ts
in the Backend to Statically Serve the Angular Frontend - Change
port
toPORT
in themain.ts
file in the Backend - Build the Frontend and Backend
- Modify
package.json
to (a) Specify Engines and (b) Run the Backend in thestart
Script - Modify the
.gitignore
File to Commit and Push Our/dist
Folder - Create a
Procfile
for Heroku - Point to Heroku and Deploy
Before we start, I’ll state some of my assumptions:
- You understand the benefits of developing your full-stack application within an Nx workspace.
- You want to build your frontend as a single-page application (SPA) using Angular and your backend API using NestJS.
- You want to deploy your application to Heroku.
- You are familiar with Angular, NestJS, Nx, Git, Node.js, Javascript, and Heroku.
- You have Node.js, Git, and the Heroku CLI installed on your computer.
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:
- “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. - “Application name?” I’ll use
nx-app
for this example. The name that you enter here will be the name of your frontend application. - “Default stylesheet format?” I’ll choose
CSS
for this example, but you can choose whichever option you prefer. - 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.
(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.
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.
(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:
ng build --prod api
to build the backend API (i.e., NestJS).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.
(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:
git add .
to stage the workspace.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.