Managing monorepos with lerna and yarn workspaces

Reusing code is a good thing, splitting your project into multiple small packages could be helpful, its' easier to focus when working on teams. It's always better to split the problem into smaller pieces.

But when it comes to managing these packages, it rapidly turns into a nightmare, things are dependent on one another, updating multiple packages and maintaing their separate repos.

That's where monorepos come in. You can have multiple packages in a single repository. They all can share the same node_modules folder. You can easily make them dependent on one another, and publish them all at once. No need of managing versions, lerna will take care of that.

Getting Started

Initialize your project with the following command.

$ yarn init

This should create your package.json file.

You must have workspaces here set to the folders where you have your packages created. Note the version here, it's 1.0.0 at start, but as you progess further, lerna is gonna update it according.

A good pattern is to use the conventionalCommits config with lerna to manage versions. You can read more about that here

Eg. package.json

Next run lerna init, you can combine the --independent flag if you wanna maintain versions of each package separately.

Eg. lerna.json

useWorkspaces option enables us to reuse the setting for Yarn Workspaces as Lerna's workspace setting.
You can switch the npmClient option from yarn to npm, if you want npm to run all your commands. Finally commands option is set to use conventionalCommits for our publish process.

Adding packages

You can create a packages folder and start adding creating your packages there or use this command $ npx lerna create @projectName/packagename.

Adding npm packages as dependencies

With yarn workspaces you don't need to cd to each packages folder in order to install dependcies, all you gotta do is $ yarn workspace @projectName/yourpackagename add npm-package-name

If you want to install shared dependencies, $ yarn add -W --dev typescript prettier eslint.

Pretty slick, right?😎

Publishing

Once you have coded your packages in the respective directories, now is the time to publish them. lerna publish is the command used to publish your packges.

If you used the Conventional Commits pattern, you can use the --conventional-commits flag with the above command to determine the version of your package. With this option, Lerna generates a CHANGELOG.md for a new version.

Here is an example.

$ npx lerna publish --conventional-commits
lerna notice cli v3.19.0
lerna info versioning independent
lerna info Looking for changed packages since @zoomify/[email protected]
lerna info getChangelogConfig Successfully resolved preset "conventional-changelog-angular"

Changes:
    - @zoomify/rest-api-client: 1.0.0 => 1.1.0
    - @zoomify/cutomize-uploader: 3.0.1 => 3.0.2

? Are you sure you want to publish these packages? (ynH)
:
Successfully published:
    - @zoomify/[email protected]
    - @zoomify/[email protected]
lerna success published 2 packages

Run npm-scripts in multiple packages

Even with the handy yarn workspaces commands, it could be frustating to test and build each and every package, if you wanna run a command across all pacakges, just do this,

Eg, let's say i wanna build all my packages before publishing.
$ npx lerna run build --stream, this will call the build command specified in package.json files of each package.

17