Make your projet as a monoRepo with PNPM

PNPM is a fast, disk space efficient package manager that helps you to manage your project dependencies.

Monorepo Image

MonoRepo is a method that manages multiple projects in a single repository, which helps to simplify the complexity of code sharing, version control, building and deployment, and provides better reusability and collaboration. Monorepo advocates an open, transparent and shared organizational culture. This method has been widely used by many large companies, such as Google, Facebook and Microsoft.

MonoRepo Evolution

Evolution Image
Staging MonoRepo

  • Phase 1: Single-repository monolith application. A Git repository maintains the project code. As the complexity of iterative business increases, the project code will become more and more numerous and complex. The efficiency of building a large amount of code will also decrease, eventually leading to a single monolith application. This code management method is called Monolith.

  • Phase 2: Multi-repository and multi-module application. The project is then broken down into multiple business modules and managed in multiple Git repositories. Module decoupling reduces the complexity of the monolithic application. Each module can be independently coded, tested, and released. Code management is simplified and build efficiency is improved. This code management method is called MultiRepo.

  • Phase 3: Single warehouse multi-module application. With the increase of business complexity, there are more and more module warehouses. Although MultiRepo is decoupled from the business, it increases the difficulty of project engineering management. As the module warehouse reaches a certain level, there will be several problems: cross-warehouse code is difficult to share; module dependency management scattered in a single warehouse is complicated (after the underlying module is upgraded, other upper-level dependencies need to be updated in time, otherwise there will be problems); and the build time is increased. Therefore, it has become a trend to integrate multiple projects into one warehouse, share project configuration, and quickly share module code. This code management method is called MonoRepo.

MonoRepo advantages and disadvantages

Comparaison Image
Staging MonoRepo

en.wikipedia.org/wiki/Monorepo has a good explanation with the advantages and disadvantages.


ScenesMultiRepoMonoRepo
Code Visibility✅ Code isolation, developers only need to focus on the warehouse they are responsible for ❌ Package management is divided according to their respective owners. When problems occur, they need to judge and solve them in the dependent packages.✅ Multiple related projects in one repository make it easy to see the change trend of the entire code base and better team collaboration. ❌ Increased risk of non-owners modifying the code
Dependency Management❌ Multiple repositories have their own node_modules, which may lead to duplicate installation of dependencies and occupy a lot of disk memory.✅ Multiple project codes are in one repository, and the same version of dependencies are promoted to the top level and installed only once, saving disk memory.
Code permissions✅ Each project has its own separate repository, so the code will not be modified by mistake, and problems with a single project will not affect other projects.❌ Multiple project codes are in one repository, and there is no project-level permission control. If a problem occurs in one project, all projects may be affected.
Development Iteration✅ Small warehouse size, clear module division, strong maintainability. ❌ Switching between multiple warehouses (editor and command line) is very inefficient if there are many projects. When multiple warehouses have dependencies, manual npm linkoperation is required, which is cumbersome. ❌ Dependency management is inconvenient. Multiple dependencies may have different versions in multiple warehouses, and repeated installation will cause conflicts between dependencies of different projects when npm linking.✅ Multiple projects are in one warehouse, you can see the whole picture of related projects, and coding is very convenient. ✅ High code reuse, convenient for code refactoring. ❌ Multiple projects are in one warehouse, the code volume is several GB, and git cloneit takes a long time. ✅ Convenient dependency debugging. In the scenario of dependency package iteration, with the help of tools, the latest version of dependency is directly used with automatic npm link, which simplifies the operation process.
Project Configuration❌ Each project builds, packages, and verifies its own code. Inconsistencies can lead to code or build differences.✅ Multiple projects are in one repository, the project configuration is consistent, and the code quality standards and style are also easy to be consistent.
Build and deploy❌ There are dependencies between multiple projects. When deploying, you need to manually go to different repositories to modify the version and deploy them in order, which is cumbersome and inefficient.✅ The buildability Monorepo tool can configure the build priority of dependent projects and complete all deployments with one command.

Monorepo with PNPM workspace

PNPM only need pnpm-workspace.yaml on your root repository alongside packages.json, with array path to directory in packages property.

1 2 3 4 # pnpm-workspace.yaml packages: - "apps/*" - "packages/*"

1 2 3 4 5 6 # Directory structure project-example/ ├─ apps/ ├─ packages/ ├─ package.json └─ pnpm-workspace.yaml

NOTE: apps/* and packages/* is very popular monorepo structure, where apps/* is projects directory and packages/* is reusable code. All you need just create directory inside packages list, change directory to it, and do pnpm init.
1 2 3 4 5 6 7 8 9 #Commands mkdir -p packages/math-lib cd packages/math-lib pnpm init cd ../.. mkdir -p apps/calculator cd apps/calculator pnpm init cd ../..

List all workspaces

1 2 #List all workspaces in JSON format. pnpm m ls --depth -1 --json

Command specific workspace

1 2 3 4 5 6 7 8 9 # Format pnpm --filter <workspace> <command> pnpm -F <workspace> <command> # Example pnpm --filter math-lib add lodash pnpm --filter math-lib add -D typescript @types/lodash pnpm --filter calculator run test # Support glob pattern pnpm --filter pkg* run test

NOTE: PNPM use name property in package.json to filter workspace, so make sure ever name in package.json is unique.

Add local dependency

1 2 # Example pnpm --filter calculator add math-lib --workspace

Project example

1 2 3 4 5 6 7 8 9 10 11 12 13 mkdir -p monorepo-example cd monorepo-example pnpm init mkdir -p packages/math-lib cd packages/math-lib pnpm init cd ../.. mkdir -p apps/calculator cd apps/calculator pnpm init cd ../.. touch packages/math-lib/index.js touch apps/calculator/index.js

1 2 3 4 5 6 7 8 //packages/math-lib/index.js const add = (a, b) => a + b; const subtract = (a, b) => a - b; module.exports = { add, subtract, };

1 2 3 4 5 //apps/calculator/index.js const { add, subtract } = require("math-lib"); console.log('9 + 10 = ', add(9, 10)); console.log('26 - 9 = ', subtract(26, 9));

1 pnpm --filter calculator add math-lib --workspace

1 2 3 4 5 6 #apps/calculator/package.json { "scripts": { "start": "node index.js" } }

1 2 3 4 5 6 #package.json { "scripts": { "calculator:start": "pnpm -F calculator run start" } }

1 pnpm run calculator:start

How i use this

Webhooks Project Image
Webhooks With PNPM MonoRepo

I worked with good craftsmen on the migration of a set of services called Webhooks that shared the same dependencies from a multirepo architecture to a monorepo. Today, the DX (Developer Experience) has been significantly enhanced with ease of maintenance, 100% redundant code reduction and almost simple handling thanks to structured documentation ranging from project initialization in a local environment to the scheme of infrastructure architecture in staging and production.
I pushed this project further by also integrating a Continuous Deployment of Releases in the different environments (staging and production) with semantically versioned docker images.

Architecture Image
Architecture Webhooks in AWS