How I deployed an Angular 9 app on Heroku with this simple workaround using Express

I am currently working on a school project that involves an API made with NestJS and a front-end made with Angular 9.

I wanted to properly set up auto-deployments from GitHub to a serverless hosting provider, so I turned to my old friend, Heroku.

Heroku can host a bunch of software projects like NodeJS, Rails, Django, and more. An app deployed on Heroku has to be able to listen and answer HTTP requests.

When an Angular app is built, we’re left with static files that have to be served to the users. With just these files, we won’t be able to get a working Heroku app.

There is a simple workaround though! I found it here.

Since we’re already using the NodeJS buildpack to build our project, let’s just add a simple, standalone Node app to serve our static files!

Install Express

For the sake of simplicity, lightness and performance, we will use Express.

npm i express

Add a simple HTTP server

Let’s add the following in server.js:

const express = require("express");

const app = express();

app.use(express.static("./dist/project-name"));

app.get("/*", function (req, res) {
  res.sendFile("index.html", { root: "dist/project-name" });
});

app.listen(process.env.PORT || 8080);

console.log(`Running on port ${process.env.PORT || 8080}`);

Here, we use the static middleware and let Express know that our static files are in ./dist/<projet-name>. We set up a catch-all route that will simply send the index.html file.

Heroku will inject a port number into the environment, so we tell Express to listen on process.env.PORT.

Add start script

Modify package.json with the following:

"scripts": {
    "start:prod": "node server.js",
    ....

Add Procfile for Heroku

The Procfile contains the command that will be run in the Dyno. For us, it’s the one we just added above.

web: npm run start:prod

Deploy and enjoy

Now, we can deploy the app to Heroku. Upon deployment, the build system will run npm run build automatically, so we don’t actually need to make further changes.

It will then launch our little Express server:

2020-04-30T19:01:12.821772+00:00 app[web.1]: > [email protected] start:prod /app
2020-04-30T19:01:12.821772+00:00 app[web.1]: > node server.js
2020-04-30T19:01:12.821773+00:00 app[web.1]:
2020-04-30T19:01:13.153430+00:00 app[web.1]: Running on port 12880
2020-04-30T19:01:13.948977+00:00 heroku[web.1]: State changed from starting to up

Simpler than expected, right? 😇