Skip to content

Instantly share code, notes, and snippets.

@morewry
Last active May 11, 2022 08:54
Show Gist options
  • Save morewry/d3419a38d74590493042544d4afa49a7 to your computer and use it in GitHub Desktop.
Save morewry/d3419a38d74590493042544d4afa49a7 to your computer and use it in GitHub Desktop.
Comparison of Monorepo Tools For Web Client / Front End Projects (That Probably Use HTML, CSS, and JS)

Mono Repository Tool Comparison

For Web Client / Front End Projects

(That Probably Use HTML, CSS, and JS)

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

⚠️ Northbrook's author says the project is pretty dead and now uses Lerna.

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 may have a feature that fills a similar 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 or done more than glance at their source code, 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 Kinda can with e.g. lerna publish --force-publish=moduleOne,moduleTwo Beware issues with --scope and --ignore! See #1055 and #1384. Isn't actually effective, the way I mean it.

  • ✅ 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 #867. Now can be assisted by Yarn Workspaces for improved sharing that is as safe as Yarn can make it.

  • ✅ "Pin" common dependencies across modules

    Can be used with NPM shrinkwrap, NPM lockfiles, or Yarn lockfiles. But see 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

    https://github.com/atlassian/lerna-semantic-release

  • ✅ Ability to use Commitizen in development

    https://github.com/atlassian/lerna-semantic-release

  • ✅ 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: 20/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 NPM dependencies and ability to deterministically install and to pin dependencies stood out. Lerna used with Yarn and Yarn Workspaces seems equal to Rush in these respects.

Northbrook

⚠️ Northbrook's author says the project is pretty dead and now uses Lerna.

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: 15/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 commit the 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.

⚠️ Northbrook's author says the project is pretty dead and now uses Lerna.

Rush

Rush Qualifications

  • 🔲 Supports both NPM and Yarn

    NPM only for now, though it's worth noting that Rush claims to be able to deterministically install NPM dependencies, which is one of Yarn's major benefits.

  • ✅ 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 checked because it's unclear if or how a root package.json is handled. As with the others, can't use for individual modules. But note this aspect 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: 12/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 that becomes a bigger issue. Side-by-side with Lerna its appeal is mainly its use of safer linking and some of the more enterprise features.

Related

Finally, here's a presentation I gave on how I'm using Lerna monorepos for Design Systems.

design-systems-and-monorepos

@morewry
Copy link
Author

morewry commented May 23, 2018

@morewry
Copy link
Author

morewry commented Jun 2, 2018

@gleber Added a subtitle

@morewry
Copy link
Author

morewry commented Jul 23, 2018

Greenkeeper now supports monorepos with multiple package.json files.

@GiriB
Copy link

GiriB commented Nov 22, 2019

Rush now works with pnpm and yarn too as per the docs here

@dwilhel1
Copy link

dwilhel1 commented Oct 12, 2020

The presentation appears to no longer be accessible:

Screen Shot 2020-10-12 at 4 49 55 PM

@morewry
Copy link
Author

morewry commented Oct 28, 2020

@dwilhel1 Updated the link, thank you! Design Systems & Monorepos.

@dwilhel1
Copy link

Thanks @morewry, it is working now!

@Logrythmik
Copy link

Seems like Lerna is dead now too.

@morewry
Copy link
Author

morewry commented Sep 15, 2021

@Logrythmik It does to some extent, I agree. I am still getting value from it for now, but with workspaces being supported by npm and yarn making improvements to its workspaces...

Who knows, though. Some of the CLI conveniences and the versioning/publishing functionality are still great and AFAIK there aren't sufficient replacements for the latter yet. Though I haven't dug into Bit enough yet to be sure how I'd feel.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment