How to deploy multiple apps in a monorepo with Heroku
At Inato, all our web apps are contained in one monorepo (front-end apps, APIs, …). We use yarn workspaces to manage all of these packages.
To host and run our apps, we use Heroku.
The standard Heroku setup only works for the 1-app-1-repo use case.
So, here is a quick guide on how to host and run multiple apps from multiple yarn workspaces contained in a single Git repository on Heroku.
Disclaimer: this guide assumes a basic knowledge of Heroku (See Getting Started).
Let’s say you have a single Git repository containing multiple applications in yarn workspaces like so:
.
├── package.json
├── packages
│ ├── web-client
│ │ └── package.json
│ └── api
│ └── package.json
└── scripts
└── heroku.build
Both web-client
and api
are web applications that need to be exposed to the network.
Using a single Procfile to expose several web processes is not possible on Heroku. You won’t be able to have api
and web
in a Procfile both exposing web apps. I.e. this does not work:
web: yarn workspace web-client start
api: yarn workspace api start
The web process type is special as it’s the only process type that will receive HTTP traffic from Heroku’s routers. Other process types can be named arbitrarily.
from the Heroku documentation.
The proper way to do it is to:
- Create one dyno for each app (workspace) you want to run
- Use the multi-procfile buildpack
- Optionally use environment variables to tweak your build step
Here’s the detail:
1. Create one dyno for each app (workspace) you want to run
Create one named Heroku app per web app using the Heroku CLI and bind it a Git remote.
$ heroku create web-client --remote heroku-web-client
$ heroku create api --remote heroku-api
Here,web-client
is the name of the Heroku app and will make the app available at http://web-client.herokuapp.com, while heroku-web-client
is the name of the git remote pointing to this heroku app and makes it possible to deploy your code to one app or the other like so:
$ git push heroku-web-client master
2. Use the multi-procfile buildpack
You need to tell Heroku how to run each of your apps. There is a buildpack provided by the Heroku team exactly for this: Heroku Multi Procfile buildpack.
Imagine you have a single code base, which has a few different applications within it… or at least the ability to run a few different applications. Or, maybe you’re Google with your mono repo?
In any case, how do you manage this on Heroku? You don’t. Heroku applications assume one repo to one application.
Enter the Multi Procfile buildpack, where every app gets a Procfile!
- Write a bunch of Procfiles and scatter them through out your code base.
- Create a bunch of Heroku apps.
- For each app, set
PROCFILE=relative/path/to/Procfile/in/your/codebase
, and of course:heroku buildpacks:add -a <app> https://github.com/heroku/heroku-buildpack-multi-procfile
- For each app,
git push git@heroku.com:<app> master
For our example, we would have one Procfile per workspace:
.
├── package.json
├── packages
│ ├── web-client
│ │ ├── Procfile
│ │ └── package.json
│ └── api
│ ├── Procfile
│ └── package.json
└── scripts
└── heroku.build
containing for instance:
web: yarn workspace api start
3. Optionally use environment variables to tweak your build step
By default, Heroku only installs Node and runs yarn install
(what it calls the “build” step). If you actually need to build something (like your front-end bundle), you can use heroku-postbuild
for Heroku-specific tasks (documentation), which is goes in the scripts
section of your top-level package.json
.
Using environment variables, you can make this script accomplish different things depending on the app.
Exemple:
That’s it !
With those steps, you can build and run different apps from your monorepo.