Obeng William
3 min readNov 5, 2018
“silhouette photography of people gathered together on cliff” by Javier Allegue Barros on Unsplash

Monorepo with lerna

At Kudobuzz we have lots of services in Nodes,js, this naturally comes with writing many reusable packages.

Now in such a situation, the most obvious way to manage these packages is to have one repo per package, but we soon found out that didn’t work quite well with us.

Setting up a ci environment for each package/repo was frustrating.

When a change required that several packages be updated, it meant that we were going to have lot of pull requests instead of a single one.

After considering other solutions we decided to give Lerna a try.

Lerna

Lerna helps you manage JavaScript projects with multiple packages.

This means if you have many services in Node.js you can basically have all of them in one repo. There are quite a number of js projects like Reactjs, Angularjs, NestJs and Shopify using it for similar reasons.

Let’s give it a try :)

We going to build a home for your organizations reusable Node.js packages. The name for our imaginary organizations will be Spot.

To get started we will install Lerna, create a folder called reusable-node-packages and then initialize Git and Lerna.

Scaffolding

sudo npm install lerna -g && mkdir reusable-node-pacakages && cd reusable-node-packages && git init && lerna init -i

Observations

// The following files will be createdpackages.json // Configuration file for npm
lerna.json // Configuration file for lerna
packages/ // Folder for all reusable package
// Inside lerna.json
{
"packages": [
"packages/*"
],
"version": "independent"
}

The most important thing to take note of is Lerna basically has two modes: independent and fixed. Fixed mode keeps all the versions of the packages at the same level. We don’t want to do that in current project , @spot/queue and @spot/logger will definitely require different versions.

Let create @spot/queue and @spot/logger

lerna create -y @spot/queue && lerna create -y @spot/logger

Observations

// Packages folder now contains queue and logger folders
// You can change the structure if you don't like this boilerplate
queue/
README.md
__tests__/ // All test can go here
logger.test.js // Test for logger.js
package.json
lib/
logger.js
logger/
...

Now we can go ahead and work on the individual packages. :)

Setting up Testing with mocha and chai

npm install mocha chai --save-dev

Observations

Well this is not exactly specific to Lerna , “node_modules” will be created in the root folder and now each package under packages will have access to the dev packages we just installed.

Update your package.json to include

{
scripts:{
test: "mocha \"packages/**/*.test.js\" // This allows you to run all your test in every package
}

You can simply run that command using npm test. Something that comes up once in a while is how I can run test just for a specific package during development. Include a similar test script for @scope/logger and @scope/queue.

{scripts: { test: "mocha lib/*.test.js"}}

To run test for @spot/logger package you can now use

lerna run test --scope logger

Publishing

To publish the individual packages, you can use the following

lerna publish

Observations

Lerna will detect changes to any of the packages and then walk you through bumping the versions for the packages that have changed before they are eventually deployed. This is a life saver, you no longer have to visit each package just to publish them.

In Conclusion

Lerna really improved our workflow, we no longer have to deal with multiple repos containing different packages, setting up ci for each of them anytime someones wants to add a new package and finally no more multiple pull request.

I hope you find this useful, Check out the final repo.

Obeng William

Aspiring Machine Learning Engineer | Entrepreneur | @MestAfrica Alumini Find me @billobeng or williamobeng.com