It almost always looks the same. You start your super-hiper-new project from the scratch — using modern technologies, the newest tech features, and beautiful simple architecture. Your clients are happy and request more and more features. Your dev team is growing and the codebase is bigger and bigger. Some day you realize your package is so swollen that you have to split it into smaller ones… And here the fun part begins! Dependency management between repos becomes a nightmare — making changes between repositories needs more and more time, testing is more complicated, the number of bugs in the final product increases and the initial setup of all repositories (and understanding connections between them) makes junior developers almost cry. Fortunately, there are many tools that may save you from that scenario. Today, I wanna focus on one of them — monorepo approach based on Lerna.js (https://github.com/lerna/lerna).
Lerna official logotype — taken from https://github.com/lerna/lerna
Monorepo is one of the approaches to manage packages in complex projects. All packages are located in the same git repository, so you keep all parts connected with the final project in one place. But at the same time, there are separated modules with independent versioning and dependencies. Each team can focus on their part, but changes are easy to test and release for the whole product. Also, you can create shared rules about e.g. linting and a common process for lint, build and release. The entry-level to project is lower because a new contributor needs to only clone one repository and call npm install & npx lerna bootstrap from the root — doesn’t care about dependencies between modules (lerna will handle it). Also, multi-packages changes are much easier. Of course, there are also cons of that approach — the repository is quite big, lerna can’t handle serverless monorepos, and may look a little overwhelming for a person who just starts work with monorepo. However, lerna can optimize the duplicated dependencies between modules (read about hoist mechanism) and a good README.md file and scripts in packages.json may help the beginners. In my personal opinion, the pros outweigh the cons. Many teams building the most recognizable software tools think the same — Babel, React and Jest are also monorepos!
npm install lerna --save-devis completely enough).
npx lerna init
lerna.json) and packages folder for your modules.
npm init). You can also use
npx lerna import <package>to transfer your existing package into lerna repository (thanks to that commit history will be preserved).
npm installdirectly from your module — use
npx lerna bootstrapinstead. Thanks to that both: existing projects in the packages folder and external dependencies will be taken into account.
"lint": "npx lerna run lint" "test": "npx lerna run test" "start": "npx lerna run start"
npx lerna publishto publish all your modules (Read about fixed/locked mode to decide if you prefer to keep one version for all packages or independents for each of them).
Dependency management is not an easy task at all. There is no golden rule answering all cases and possibilities. Each project should be considered individually. But existing general approaches (like monorepo) and tools (like lerna) may help you to make a decision and avoid some mistakes. It’s why I strongly advise you to think about it and play a little with monorepos (e.g. in your side projects) — even if it’s not really necessary at this time in your main project. Maybe it will be useful with another? Or when your project will grow? Good luck