Lately, I’ve been hearing and talking a lot about ways to scale code-sharing. A popular topic is the “monorepo”, or a multi-package shared repository.
Keeping separate packages inside a single repository is useful for code-sharing as it enables teams to share parts of their projects for other teams and projects to use, without the overhead of setting up and maintaining many repositories.
For example, imagine an organization where different frontEnd teams wish to collaborate and work with shared React components. To support that, they built a shared React library (like Pinterest’s Gestalt or HP’s Grommet).
To make this possible they think about going “monorepo”; keeping all components in a single repository while each is its own package. This “useful evil” also makes it easier to contribute, run CI/CD and manage changes.
In this post, I’ll review and share knowledge about the best tools and solution in the ecosystem for making this possible. Feel free to comment and suggest your own insights and tools from your experience!
The thing about Bit is that every repository is already a monorepo.
You don’t need to refactor anything. You don’t need to restructure the project, set up different packages, define package.json
files or anything else.
Instead, you just need to add Bit to the repository and share the components. This becomes possible thanks to Bit’s ability to automatically isolate components from the project, including all their dependencies and more.
Dozens of components can be shared within minutes from adding Bit to the repository, to become available in Bit’s hub, where they can be organized, shared and played-with online, then installed with NPM and Yarn.
When you make changes to one component in the repository, Bit will automatically track the changes and identify other components which use it as a dependency. Then if you run bit status
you can see all the components which were automatically modified as their dependency was modified.
Made changes to 1 component in the repo; Dependents were automatically updated
Meaning, no manually going through package.json
files to manage changes to dependencies, as Bit does this work for you to make your monorepo maintenance much simpler.
You can also add Bit to your library’s release management (CI/CD) to update the components on every release with all the changes. Since Bit runs, build and test your components, you can quickly learn the new status of everything.
PRs can be made directly to the monorepo, or via bit import
which lets others import and develop components right from their end project.
To sum up, if you have a component library you want to make a multi-package monorepo, Bit is probably the fastest and lowest-effort way to go about it. It also provides added values as discoverability, an online community and more.
Semantic-UI component library before Bit.
Semantic-Org/Semantic-UI-React_The official Semantic-UI-React integration. Contribute to Semantic-Org/Semantic-UI-React development by creating an…_github.com
Semantic-UI component library with Bit (0 refactoring).
teambit/Semantic-UI-React_The official Semantic-UI-React integration. Contribute to teambit/Semantic-UI-React development by creating an account…_github.com
package.json
files to maintain or update.
Lerna is a tool for managing multiple packages within a single repository.
With Lerna you can refactor your repository to keep multiple packages within it, while Lerna allows you to link dependencies (lerna bootstrap)
and version them all separately or together as you choose (Independent mode would mean that every sub-package would have its own semver and get updated accordingly when its dependencies got updated).
my-lerna-repo/ package.json packages/ package-1/ package.json package-2/ package.json
Lerna automates tasks for packages in the monorepo. Thelerna run build
will run npm run build
inside each sub-package and lerna publish
will publish all packages to npm and will update git tags, etc. Then, packages can be installed from NPM’s registry.
Lerna requires some work at the get-go and more along the way, but is a solid way to keep a small number of core packages in a single repository and publish each independently to NPM.
Some open-source projects use Lerna to handle core packages, including Babel, Jest and Gatsby. It has many tutorials and posts around the web. It’s particularly useful for managing several parts of a single project in one repository, while each is a stand-slone “mini-project” on its own.
babel/babel_🐠 Babel is a compiler for writing next generation JavaScript. — babel/babel_github.com
lerna bootstrap
.Lerna publish
publishes all updates to NPM.package.json
and environments for every package.
Lerna and Bit can play together in a single repository.
For example, Lerna can be used to manage the core packages while Bit can be used to share all smaller components. Bit also provides discoverability for components, and reduce the amount of refactoring and maintenance needed.
The two can also play with Yarn workspaces. While Bit will automatically manage dependencies between the components in the repository and Lerna will help you handle larger core packages, Workspaces will help consolidate and optimize the installation of external packages in the repository.
Git is the SCM of choice for most dev-teams. It allows you to put one repository as a subdirectory of another repository, creating a single working-tree for the entire project, and one project can use code from another project.
But… Git submodules is, for most developers, a painful topic.
First, they only work on master
branch. Second, submodules create highly coupled code between projects and make it hard to merge and collaborate on cross-repo tasks. A submodule repo also has no idea that it is nested, and might have a dependent repo.
There are various tools that provide additional automation around the Submodule feature, such as git-subtree, gitslave, braid and giternal. These tools try to improve some of the usability issues of Submodules, but are not supported by a specific vendor and have different drawbacks.
The discussion around Monorepos is thriving in the community. While most agree on the virtues of a multi-repo architecture, some use-cases make it just too hard to maintain and publish multiple packages from multiple repositories. Particularly, when working on a shared library.
To make this easier, new tools emerged in the ecosystem. From Lerna which automates the setup around keeping and publishing larger packages in a single repository, to Bit which takes the experience around component libraries to the next level, at 0 effort and with all the benefits.
Down the line don’t forget, that sharing code is about technology but also about people. You and your team have to be oriented to writing reusable code, thinking in modularity and encourage communication and efficiency. Thanks for reading, and please don’t hesitate to comment below and ask anything. Cheers