Managing monorepos with lerna and yarn workspaces
Tags: typescript, javascript, webdev, npm
Published: 2021-07-15 05:14:02

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.

![Cool huh, gif](https://github.com/tevez07b9/courscate/raw/master/7c868c27-9989-48c7-b6b5-b108f9416743_text.gif)

### 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](https://www.conventionalcommits.org/en/v1.0.0/)

Eg. `package.json`
{% gist https://gist.github.com/tevez07b9/ce156341b7b278b12e9ca808a0730c69 %}

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

Eg. `lerna.json`
{% gist https://gist.github.com/tevez07b9/d3179ee4a5106b7804983fbbffd85667 %}

`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](https://www.conventionalcommits.org/en/v1.0.0/) 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/rest-api-client@1.0.0
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/rest-api-client@1.1.0
    - @zoomify/customize-uploader@3.0.2
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.

![that's cool](https://github.com/tevez07b9/courscate/raw/master/tenor.gif)