I made a list of 20 things I might want out of a monorepo tool to use as a basis for comparing some of the options for managing mono repositories including Lerna, Northbrook, and Rush.

Qualifications Wanted

  • Supports both NPM and Yarn: We have projects using both, plus options are good.
  • Build one, some, or all modules: Change detection is nice, but also looking at whether a user can choose.
  • Test one, some, or all modules: See if there’s any specific features, otherwise overlaps with arbitrary commands.
  • Distribute one, some, or all modules: Change detection is nice, but also looking at whether a user can choose.
  • Distribute arbitrary bundles: See if there’s any way to compose ad hoc bundles, or at least be able to make a bundle module.
  • Run arbitrary commands and tasks for one, some, or all modules: I view this as one of the most important core features.
  • “Share” dependencies across modules safely: I view this as one of the most important core features.
  • “Pin” common dependencies across modules: I view this as a very important feature.
  • “Link” module-to-module dependencies safely: I view this as one of the most important core features.
  • Install unique dependencies for individual modules: I view this as one of the most important core features.
  • Distribute to a pre-release channel: See if there’s any specific features, otherwise overlaps with arbitrary commands.
  • Parallelization of tasks: Need depends on the project, but potential monorepo size makes this something to consider before you need it.
  • Support change log generation: See if there’s any specific features, otherwise overlaps with arbitrary commands.
  • Support documentation generation: See if there’s any specific features, otherwise overlaps with arbitrary commands.
  • Support UI style guide generation: See if there’s any specific features, otherwise overlaps with arbitrary commands.
  • Ability to use Semantic Release in distribution: The tool’s release feature may fill need, but options are good.
  • Ability to use Commitizen in development: The tool’s release feature may fill need, but options are good.
  • Ability to use Greenkeeper for dependencies: Support for multiple package.json may be more a feature for Greenkeeper, but want to make a note.
  • Sufficiently documented: Is there enough to get started and to go deeper as use evolves?
  • Community Activity: Are other developers posting about it? What’s the GitHub activity like?

Tools

Research was done using the documentation, googling for articles, checking out issues, and a little poking around on basic demo repos. I haven’t used any of these tools extensively yet, so if you see anything I have wrong, please let me know. Tools included are Lerna, Northbrook, and Rush.

Lerna

Lerna Qualifications
  • Supports both NPM and Yarn
  • Build one, some, or all modules
    With e.g. lerna run build or lerna exec --scope moduleOne -- gulp build
  • Test one, some, or all modules
    With e.g. lerna run test or lerna exec --scope moduleOne -- gulp test
  • Distribute one, some, or all modules
    Has both fixed and independent options. With e.g. lerna publish will distribute any with changes With e.g. lerna publish --force-publish=moduleOne,moduleTwo
  • Distribute arbitrary bundles
    With e.g. lerna publish --force-publish=bundleOne
  • Run arbitrary commands and tasks for one, some, or all modules
    With e.g. lerna run {{whatever}} NPM scripts run conditionally With e.g. lerna exec --scope moduleOne,moduleTwo -- {{whatever}} anything
  • “Share” dependencies across modules safely
    Almost with lerna bootstrap --hoist, except see Lerna issue #867
  • “Pin” common dependencies across modules
    Maybe able to use normal NPM install with shrinkwrap/package-lock or Yarn? But see Lerna issue #377
  • “Link” module-to-module dependencies safely
    With e.g. lerna bootstrap
  • Install unique dependencies for individual modules
    With e.g. lerna bootstrap
  • Distribute to a pre-release channel
    With e.g. lerna publish --canary
  • Parallelization of tasks
    Has relevant options including --stream, --parallel, and --concurrency
  • Support changelog generation
    With e.g. lerna publish --conventional-commits or lerna run or lerna exec
  • Support documentation generation
    With e.g. lerna run docs or lerna exec -- gulp docs
  • Support UI style guide generation
    With e.g. lerna run styleguide or lerna exec -- gulp styleguide
  • Ability to use Semantic Release in distribution
  • Ability to use Commitizen in development
  • Ability to use Greenkeeper for dependencies
    Only for top level package.json, not individual modules. But note this may more appropriately be a feature for Greenkeeper to support.
  • Sufficiently documented
    Good documentation for getting started and a little beyond, not great yet
  • Community Activity
    Some community posts, active on GitHub
Lerna Notes
  • Has required configuration file created by lerna init
  • Can use custom project structure
  • Seems to support non-master branches with --since flag
  • Builds in debugging with --loglevel and lerna-debug.log
  • Has import command for combining previously separated repos into a monorepo
  • Has a number of additional configurations, commands, options, and flags that may be useful
Lerna Score

Score: 17/20

Perhaps unsurprisingly, Lerna did the best at meeting the qualifications, although Northbrook has appealing simplicity and flexibility and Rush’s relatively safer strategy for sharing dependencies and ability to deterministically install and to pin dependencies stood out.

Northbrook

Northbrook Qualifications
  • Supports both NPM and Yarn
  • Build one, some, or all modules
    With e.g. nb --only moduleOne,moduleTwo exec -- npm run build
  • Test one, some, or all modules
    With e.g. nb --only moduleOne,moduleTwo exec -- npm run test
  • Distribute one, some, or all modules
    Seems to have both fixed and independent options. With e.g. --comver is default, independent presumably via --semver With e.g. nb release --only moduleOne,moduleTwo also supports detecting changes.
  • Distribute arbitrary bundles
    With e.g. nb release --only=bundleOne
  • Run arbitrary commands and tasks for one, some, or all modules
    With e.g. nb --only moduleOne,moduleTwo exec -- {{whatever}}
  • “Share” dependencies across modules safely
    Supported with package.json in root and plugin system. Result should be similar to Lerna, however.
  • “Pin” common dependencies across modules
    Can use normal NPM install with shrinkwrap/package-lock or Yarn.
  • “Link” module-to-module dependencies safely
    With e.g. nb link
  • Install unique dependencies for individual modules
    With e.g. nb exec -- npm install
  • Distribute to a pre-release channel
    Possibly as arbitrary command, otherwise appears unsupported.
  • Parallelization of tasks
    Not mentioned anywhere, so appears unsupported.
  • Support changelog generation
    Users can generate from nb commit format, write custom plugins, etc.
  • Support documentation generation
    With e.g. nb exec -- npm run docs or write a plugin.
  • Support UI style guide generation
    With e.g. nb exec -- npm run styleguide or write a plugin.
  • Ability to use Semantic Release in distribution
    Doesn’t appear to be any existing integration, could write a plugin. Unclear if you could replace nb release.
  • Ability to use Commitizen in development
    Doesn’t appear to be any existing integration, could write a plugin (or just use alongside?). Unclear if you could replace nb commit. Unclear how a non-conventional commit format would impact nb release. But it passes because it does support plugins and by-module tasks, meaning tooling around the related areas will be easier.
  • Ability to use Greenkeeper for dependencies
    Only for top level package.json, not individual modules. But note this may more appropriately be a feature for Greenkeeper to support.
  • Sufficiently documented
    Enough documentation for basics, but not quite good yet.
  • Community Activity
    No community posts found, some activity on GitHub.
Northbrook Notes
  • Has a required configuration file & manifest
  • Can use custom project structure
  • Supports non-master branches with --release-branch flag
  • Builds in --debug
  • Extensible, plugin oriented architecture
  • Based on a tool for making composable command line apps
Northbrook Score

Score: 14/20

Northbrook’s design is really appealing to me personally, but as it is mostly an orchestrator of plugins and I’d rather use Semantic Release and Commitizen directly for functionality like nb release and nb committhe appeal over Gulp is mostly in nb exec and nb link. Its relatively lower profile in the community in comparison to Lerna is also, unfortunately, persuasive.

Rush

Rush Qualifications
  • Supports both NPM and Yarn
    NPM only for now
  • Build one, some, or all modules
    User defines NPM test script, Rush assumes it builds and tests. With e.g. rush rebuild --to moduleOne --to moduleTwo
  • Test one, some, or all modules
    User defines NPM test script, Rush assumes it builds and tests. With e.g. rush rebuild --to moduleOne --to moduleTwo
  • Distribute one, some, or all modules
    Change detection based with rush change and rush publish. Unclear if able to force changes. Maybe always using rush publish --include-all could simulate fixed versioning?
  • Distribute arbitrary bundles
    Probably, with a bundleOne module and above.
  • Run arbitrary commands and tasks for one, some, or all modules
    Can still set up tooling and run commands normally, but doesn’t assist with by-module tasks.
  • “Share” dependencies across modules safely
    Supported with implicit pinning during rush install. Unclear if or how a root package.json is handled.
  • “Pin” common dependencies across modules
    With rush generate it makes installs deterministic. Also has a manual pinning option.
  • “Link” module-to-module dependencies safely
    With e.g. rush link
  • Install unique dependencies for individual modules
    Happens during rush install.
  • Distribute to a pre-release channel
    At minimum, can make pre-release versions with --prerelease-name flag.
  • Parallelization of tasks
    Supported and has --parallelism flag. Also does subset builds, provides incremental through optional Gulp integration.
  • Support changelog generation
    It appears so, how is unclear; seems to have to do with rush change. Then rush publish will automatically generate one according to docs.
  • Support documentation generation
    It appears it might have an “AEDoc” (API Extractor) integration. But would have to set up custom in project root, and Rush doesn’t assist with by-module tasks.
  • Support UI style guide generation
    Would have to set up custom in project root, and Rush doesn’t assist with by-module tasks.
  • Ability to use Semantic Release in distribution
    Would have to set up custom in project root, and Rush doesn’t assist with by-module tasks. Also unclear if you could replace rush publish.
  • Ability to use Commitizen in development
    Doesn’t appear to be any existing integration, could just use alongside? Not marking because it’s unclear if it’s possible to integrate with rush publish changelog, which would add complication since Rush doesn’t assist with by-module tasks.
  • Ability to use Greenkeeper for dependencies
    Not for individual modules. Unclear if or how a root package.json is handled. But note this may more appropriately be a feature for Greenkeeper to support.
  • Sufficiently documented
    Okay documentation, have to fill in with CLI -h. Missing some critical parts about rush change, etc.
  • Community Activity
    No community posts found, some activity on GitHub
Rush Notes
  • Has a required configuration file & manifest
  • Can use custom project structure
  • Supports non-master branches with --target-branch flag
  • Builds in --debug
  • Has some enterprise-targeting features that might be useful
  • Rush is at its most robust if you use their optional Gulp plugins
Rush Score

Score: 11/20

At first, I thought I’d end up favoring Rush because of how well their doc explained the underlying functionality of rush install. But I couldn’t find some relevant and clearly necessary-to-me docs about how rush change works; on the test repo I always got output that No change file is needed. Combined with a lack of findable posts from developers and that becomes even more of an issue. Side-by-side with Lerna its appeal is mainly its use of safer linking and some of the more enterprise features.