Monorepo on Heroku in TypeScript: Part 2

We update the application to include Redis and the worker process.

Image for post
Image for post

This article is part of a series starting with Monorepo on Heroku in TypeScript: Part 1.

The final example for this series is available for download.

Redis Service

For local development, we need to spin we spin up a Redis Docker container with:

docker run --name some-redis -p 6379:6379 -d redis

For the Heroku application, we execute the following from the project folder:

heroku addons:create heroku-redis:hobby-dev

We configure the Heroku local environment for Redis; the environment for the Heroku application is automatically set.

.env

Update web Package

We install kue; a priority job queue backed by Redis, built for Node.js.

npm install kue
npm install @types/kue

We update (and commit) the Express application; implementing an endpoint to add jobs to the queue; returning results when the jobs complete.

We can then locally run the application with:

heroku local

and on Heroku:

git push heroku master

Observation:

  • Without the worker process, the web service will not return a result

Create worker Package

We begin by creating a folder, worker, in packages and copying the following files from the web package:

  • .gitignore
  • package.json
  • tsconfig.json
  • tslint.json

We update (changing the name, entry point to worker.js and getting rid of the dependency on Express):

packages / worker / package.json

We then write the code for the worker process:

We then update the Heroku process file:

Procfile

We can new start the application locally and browse to it:

heroku local
Image for post
Image for post

Observations:

  • The string, apple, is generated by the worker process from a job in the queue (backed by Redis)

We then commit our changes and push it to Heroku.

git push heroku master

Then enable the Heroku application to run the worker.

heroku ps:scale worker=1

Finally, we can browse it with:

heroku open

A New Problem

First, we solved our original problem, i.e., each of the packages (web and worker) have completely separate dependencies.

The build time for this particular application is minimal; the code is super simple. On the other hand, as the code becomes more complex and we add more packages, the build time for the application can become lengthy (tens of minutes).

The lengthy build time is especially bothersome when changes only involve a single package; the current configuration always builds all the packages.

The Solution

While one can imagine complex solutions to determine which packages to build, here is a quick and somewhat hackish solution:

  • We change out the simple postinstall command with a more comprehensive script (below)
  • The script’s behavior is. If a file named build exists at the root of the project, it will interpret it as a list (one per line) of packages to build; otherwise it builds all the packages

postinstall.sh

Observations:

  • First, thought to write this as a Node.js application, but in the end found a simple shell script solved the problem
  • This particular script requires that the package names (in the respective package.json files) match the folder names

Wrap Up

Hope you found this useful.

Written by

Broad infrastructure, development, and soft-skill background

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store