July 10, 2020component librarieslerna
Imagine that you’ve been doing a bunch of research, and you’ve decided to structure your team’s component library as a monorepo. You’re probably feeling excited — you’ve finally made a decision! And then it hits you — now you have to make another decision:
You should choose option #2.
You’re probably an awesome developer. You could definitely write these scripts yourself. It might even be a great learning experience for you to try. But when you’re done you still won’t be any closer to accomplishing your actual goal: 🚢 shipping a component library.
The opportunity cost –– the work you’re not doing so that you can write custom scripts –– is far too high. All of the time you spend writing custom scripts is time you’re not spending on the core feature-set of your project –– the actual components!
Lerna is an open source project that handles two core workflows in library development:
I promise, using Lerna will save you tons of time. You’ll be able to automate common workflows (like publishing to a registry) almost immediately. It has a lot of commands, but there are two core commands that will provide you with 80% of the library’s value.
lerna bootstrap installs all of your packages dependencies across the project, and links your packages. This allows library developers to work on multiple packages that rely on each other simultaneously in development without having to manually
npm link packages together across multiple repositories.
lerna version allows you to assign a new version number to an updated package.
When you run
lerna publish, Lerna will publish new versions of your packages to your registry, where consumers will be able to install and use them.
This is where we start to get into the murky world of “it depends.” Different teams have slightly different workflows based on their tool preferences and specific business needs.
Remember, Lerna is just a collection of scripts. It works well with other tools, and running the scripts can be automated during your build step. I’d recommend versioning and publishing your packages manually for a few weeks to get the hang of the process. You’ll start to discover that you run the same commands in the same order.
You’ll also recognize steps you need to supplement or steps that you can further simplify with automation. For example, you might want to publish a build to your registry without releasing a new semantic version, otherwise known as a “canary build.” Or you might not want to manually set a semantic version, and you’d prefer to use Conventional Commits.
I’d like to share an example of how we structure this workflow in the component library that I currently work on at Harry’s, called the Forge. It’s a monorepo that contains a
/packages directory. Inside of
/packages we have multiple libraries. Some are individual components, like
button, while others are CLIs, GraphQL resolvers, and other types of packages.
We use CircleCI for our
CI/CD pipeline, so that’s where we run our commands to version and publish our packages to JFrog Artifactory (this is just where our private registry lives). The (simplified) workflow looks like this:
lerna publish(triggered by merging to master), or
lerna publish --canary(triggered by opening a PR with a branch prefixed with
You’ll probably end up with something different from what we have at Harry’s, but hopefully this example helps you to see how these steps might fit together, and where Lerna can fit into your build process.
You can use it to link all of your dependencies so that it’s easier to develop across packages, and you can use it along with Conventional Commits to version and publish your libraries to a private or a public registry.
Are you researching monorepos and Lerna for something you’re building? What are you stuck on? I’d love to hear from you. You can reach me on Twitter or by responding to any of my newsletter messages. (Seriously, I really want to hear from you.)
Whether you're new to design systems or a seasoned pro, this newsletter is for you.
Join over 70 developers learning about design systems now: