Software development is an ever-evolving space where languages, tools, and best practices can rapidly change based on the market. Yet there is always a race to do things faster and better than before.
The goal of this blog is multifold. We’ll start by defining what a monorepo is at a high level. Then, I’ll explain what Turborepo is, and we will go over how to create a monorepo using Turborepo. Finally, I’ll give you a breakdown of Turborepo’s structure.
What is a Monorepo?
A monorepo is a repository design in which multiple projects/applications live. This type of design allows for easy code reuse, improved cross-team collaboration, simplified dependency management, and improved code consistency.
Frontend monorepos, in particular, often work best for a set of projects that share a common theme and need to be kept in sync with one another, as it allows for shared components and consistency across project dependencies.
Note, however, that monorepos should not be confused with monolithic architecture, which is the software practice of having self-contained applications. While monorepos often contain multiple projects that are usually related, they can be run independently of one another. Google, Microsoft, and Airbnb are a couple of well-known companies that use monorepos.
Additionally, while there are many positives to monorepos, always remember that in order for them to be effective, proper tooling is needed. This is where Turborepo comes in. Turborepo offers a solution to the biggest downside of monorepos: how poorly they can scale without the proper tools.
What is Turborepo?
Turborepo addresses duplicate work by creating a cache the first time a task is run. If no code for that section is changed but the task is run again, it references the cached result and does not waste time rerunning the task.
This is automatically used for local builds, and it can also be set up so that remote automation tasks or even other team members can take advantage. This is especially useful for monorepos because most of the time, you will only be working on a subset of code and can avoid having to build the entire project over and over.
Task scheduling is another workflow that Turborepo helps optimize. Their official documentation goes over it in great detail. Essentially, it boils down to running as much in parallel as possible while making full use of the hardware it’s on to maximize performance.
Now that you have an understanding of what a monorepo is and how Turborepo can help, I’d like to go over a quick example of how to implement a monorepo using Turborepo.
More specifically, I will be outlining how to use Turborepo to create a new frontend monorepo with the intention of using shared components across projects within said monorepo. For those of you that may be thinking of adding Turborepo to an existing project or existing monorepo, I recommend checking out their documentation here and here (respectively).
First, you will have to install a package manager. For this tutorial, we will use
npm, but Turborepo also supports
After installing npm, run
npx create-turbo@latest to create the base example. This will prompt you for the location you would like your new repo and what package manager to use for the project.
We will once again be using
npm for simplicity, but Turborepo itself recommends
pnpm if the user has no preference. Pick your favorite as there are very few differences in terms of how Turborepo is set up depending on what you pick. The main difference in package managers from a Turborepo perspective is how inner dependencies are referenced (
That’s it. You’ve now generated your own monorepo using Turborepo!
If you have a specific tech stack, I would recommend checking the examples page first. It offers multiple different tech stacks such as
Gatsby.js, and others.
Turborepo Project Structure
After creating your new repository using Turborepo, you will be greeted with (essentially) the same layout regardless of what starter you used. It can be broken down into 3 main sections, the
apps folder, the
packages folder, and the
apps folder is where all the projects in the created monorepo live. In Turborepo’s case, this means all the
Gatsby projects live here.
These projects can also be called workspaces, which just means that they can have their own dependencies, run their own scripts, and can export code into other workspaces.
packages folder is similar to the
apps folder in that it contains workspaces. Unlike the
apps folder, though, it is more focused on configuration for things like eslint and tsconfig, along with shared components that may be used across applications in the
The turbo.json file, on the other hand, is where you manage any tasks run for all of the workspaces. It’s where the Turborepo-specific commands are set up. By default, it will have built-out commands for linting, building, and running the projects, but any command you can think of can also be added.
This file is like the beginning of a set of dominos where you trigger the child workspace scripts by knocking over the first domino (or running the script defined in this file). Note, however, that in order for the script to run for a workspace, the workspace must also have a script with the same name so that Turborepo knows what to trigger.
That about covers all you need to know to get started with Turborep! While monorepo development can be a daunting proposition on its own, tools like Turborepo are around to make it easy to manage.
Thanks for sticking around til the end, and if you want to learn about even more topics, the Keyhole Software Dev Blog is a great place to start.