The largest software companies in the world use monorepos. But historically, adopting a monorepo for anything other than at a Facebook or Google scale was difficult, time-consuming, and often filled with headaches.
Turborepo takes the lessons and development workflows from the giants of the Web and brings it to open source for every developer. It lowers the barrier to entry for using monorepos and makes it accessible to everyone.
Let’s explore how monorepos can improve your development workflow.
Monorepos are codebases containing multiple projects, often using multiple frameworks, in a single unified code repository. Rather than having 100+ separate repositories, teams instead choose to consolidate to a monorepo for a number of reasons:
- Easier updates across packages
- Easier collaboration and debugging
- Easier local development
- Faster builds with remote caching
Monorepos empower software teams to be more collaborative and productive with improved transparency, discoverability, code sharing, and standardization. But colocation of code doesn’t solve every problem.
Instead of wasting days worrying about how you're shipping, Turborepo lets you focus on what you're shipping by abstracting configuration, scripts, and tooling on your behalf.
Turborepo has drastically improved developer productivity at Makeswift, helping us get to market faster.
Let’s look at some of the advantages of using monorepos and explore how Turborepo makes them easy to adopt.
Let’s say you have a component library being reused across 100 different repositories, distributed as an npm package. Publishing a new version of the component library and updating all 100 repositories can turn into a nightmare. Different repos quickly get out of date and discrepancies in your application begin to appear. (Why does the button look different on this page? Oh, it’s using a different version of the component library.)
With monorepos, updating the version of a package can happen in a single place and cascade to all other dependencies. This helps ensure consistency across products and features and prevents the pain of trying to coordinate commits across multiple repositories.
With Turborepo, we were able to give each workspace its own build, test, and typecheck scripts and not worry about manually managing when they execute — Turbo handles the pipelining and caching. Turbo remote caching has drastically sped up our CI runs when a code change only touches one or a few workspaces.
Try out the Turborepo design system starter to build your own component library.
When critical pieces of your system are distributed across many repositories, it’s hard to find the code you’re looking for. With all code living in a single place, it’s easier to search, share, and reuse code across different systems, applications, or libraries. Plus, it’s easier to enforce standards across the organization in a centralized location.
With separately published repositories, the current tooling (
npm link) makes it difficult to make changes to shared components or services. This method struggles to scale as the number of repositories grows. It’s not feasible to globally symlink 100 repositories together to run an end-to-end test on your local machine.
With monorepos, we can set up testing, linting, formatting, publishing, and other tasks once in a single place where dependencies can be easily managed and upgraded together. This helps prevent toolchains for less active applications from falling behind, making it easy to run locally when revisiting the application later.
Turborepo has saved us 67 hours of CI since we adopted it. That's for a team of only four full-time developers.
Try out the Turborepo example with pnpm for the fastest local development experience.
Turborepo caches the output of any previously run command such as testing and building, so it can replay the cached results instantly instead of rerunning them. Normally, this cache lives on the same machine executing the command.
However, with remote caching, you can share the Turborepo cache across your entire team and CI, resulting in even faster builds and days of time saved. This speeds up your workflow by avoiding the need to constantly re-compile, re-test, or re-execute your code if it is unchanged.