Exploring the use of a monorepo (Lerna) for flexible dependency management of Heroku processes (dynos).
Just wrapped up an article, Worker Processes with Heroku By Example, demonstrating a Heroku application consisting of:
- PostgreSQL database (not required for that article, but the configuration was carried over from prerequisite instructions)
- Redis in-memory key-store
- web process (dyno) interacting with Redis
- worker process (dyno) interacting with Redis
One of the aspects of that example is that the web and worker processes are built with the same dependencies; there is only one package.json. What happens if one wants to update the dependencies of only one of them? No luck!
Thought back to a series I wrote, Monorepos By Example: Part 1, and how it addresses this very issue using a monorepo (built using Lerna). Thought to explore refactoring the example this approach; will assume that you have some basic familiarity with Lerna, Heroku, and TypeScript.
The final example for this series is available for download.
Requirements (as before):
- Heroku Account
- GIT Software: Distributed version control system
- GitHub Account: GIT repository sharing hub
- Heroku CLI Software: Heroku command line interface
- Docker; for local services during development
Create Lerna Monorepo Project
In an new folder we execute:
npx lerna init
Update; updating name and adding scripts:
- After Lerna is installed with, npm install, the project will use it to bootstrap (install each of the packages’ dependencies) and build-ts (build each of the packages)
Create web Package
We create a folder, web, in the packages folder with the final TypeScript example from the TypeScript Node Starter Simplified article; essentially an Express Hello World application written in TypeScript with linting.
packages / web / src / package.json
We update the web server’s port to accommodate Heroku.
packages / web / src / server.ts
Create Heroku Application
We then commit all of our changes (using whatever GIT tools you prefer).
We then create a Heroku application.
heroku create monorepo-heroku
We also disable the pruning of devDependencies.
heroku config:set NPM_CONFIG_PRODUCTION=false
- If pruning is enabled, the package-level devDependencies are prematurely pruned after the bootstrap step and before the build-ts step; thus breaking the Heroku build
We push the application to Heroku.
git push heroku master
and to open a browser to the see the output
In the next article, Monorepo on Heroku in TypeScript: Part 2, we update the application to include Redis and a worker process.