A simple monorepo sample reference using turborepo, lernajs and pnpm
Managing monorepos has become more than a trending topic but a key argument to consider and to master in managing large and complex projects, or even projects including multiple packages. There is a huge literature all around about techniques, management, pros&cons, benefits and more, a good place to find references could be Awesome monorepo.
Usually managing monorepos in nodejs/javascript is often made using lernajs althought some alternatives during the time has been implemented, The basic toolchain usually relied on lerna and a package manager between npm and yarn.
Althought there are several tools and farmeworks too to manage monorepos for several languages & runtimes, this repository aim to provide a simple sample reference for nodejs monorepos considering a powerful and strong toolchain splitting the responsibilities in:
- Build system
- Monorepo management
- Package management
- Configurable build system
- Dependency hoisting
- Workspace management
- (Independent) Packages versioning
- Conventional commits
- Commit message linting
- Changelog generation per package
- Git integration
This monorepo configuration makes use of the following packages per feature:
Feat | Name | Package(s) | Notes |
---|---|---|---|
Configurable Build System | Turborepo | turbo |
|
Packages versioning | Lerna | lerna |
|
@lerna/project |
|||
Dependency hoisting, Workspace management | Pnpm | - |
|
Conventional commits | Committizen | commitizen |
|
cz-conventional-changelog |
|||
cz-lerna-changelog |
|||
Commit message linting | Commitlint | @commitlint/cli |
|
@commitlint/config-conventional |
|||
@commitlint/core" |
|||
@commitlint/prompt |
|||
Git integration | Husky | husky |
1. Workspaces
- enabled through pnpm within the file
pnpm-workspace.yaml
- manage packages in
packages
folder - exclude everything inside any
test
folder
- configured within
.npmrc
file shamefully-hoist: true
3. Packages management & resolution
- configured within
.npmrc
file prefer-workspace-package: true
save-workspace-protocol: false
1. version command enhancement
- configured within
lerna.json
file, versioning supported only inmain
branch using conventionalCommits through achore(release)
message:... "command": { "version": { "allowBranch": "main", "conventionalCommits": true, "exact": true, "message": "chore(release): %s" } }, ...
2. version independent
- configured within
lerna.json
file, permit an independent versioning strategy per affected package:... "version": "independent", ...
3. npmClient override
- configured within
lerna.json
file, permit to use as npmClient a different package manager, here pnpm... "npmClient": "pnpm", ...
4. workspaces
- althought workspaces are managed and configured using pnpm, lerna requires to have visibility of such configuration within
lerna.json
file... "useWorkspaces": "true", ...
1. Changelog generation per package
- configured within
package.json
file, permit to specify what strategy to use for changelog generation based on conventional commits. Considering the independent versioning management per package through lerna, the packagecz-lerna-changelog
permit to manage it according to monorepo packages:... "config": { "commitizen": { "path": "./node_modules/cz-lerna-changelog" } } ...
conventional commits are then managed via terminal as
1. Git integration
- configured within
package.json
file, permit to apply linting to commit messages... "husky": { "hooks": { "commit-msg": "commitlint -e $HUSKY_GIT_PARAMS" } }, ...
1. Turborepo integration
- configured within
package.json
file
...
"turbo": {
"baseBranch": "origin/main"
},
...
Note: Although Turborepo support a rich and versatile configuration and toolchain for managing monorepos, this monorepo is configured for minimal integration alongside to lernajs for versioning and changelog generation.
At present, a sample pipeline is not yet configured.
The actual monorepo configuration support the management of packages within the usual packages
folder
As a sample structure, there are two sample packages
both are implemented using a sample Fastify structure with:
The monorepo manage the following scripts:
Name | Purpose | Notes |
---|---|---|
preinstall |
check no package manager can be used but pnpm | |
commit |
execute conventional commits prompt | |
build |
execute the build using turbo repo build system | A pipeline is required in order to execute |
dev |
execute the dev script using turbo repo build system | A pipeline is required in order to execute |
lint |
execute the linter using turbo repo build system | A pipeline is required in order to execute |
format |
prettify code files | C3 |
clean |
perform a global monorepo cleanup | shortcut for clean:artifacts |
clean:artifacts |
perform a cleanup purging all node_modules folders | recursive |
run:service:one |
execute the run script and start service-one | service-one on PORT 3001 |
run:service:two |
execute the run script and start service-two | service-two on PORT 3002 |