Catalin Ciubotaru avatar

I tried Turborepo and I liked it

Drink the Kool-Aid and add some a computational cache solution to your repo.

The Problem

You always want your build, lint, test and even your format:check commands to be as fast as possible. Maybe even instant ⚡️. Well, let's talk about that.

Good to know before jumping in

In this post I'll talk about TurboRepo and a bit about Nx. Please read the docs before jumping into any of these tools. This is not a tutorial.


There are five parts to this post:

  1. Candidates
  2. Previous Experience with Nx
  3. Compromises
  4. Turborepo setup
  5. Turborepo advantages


If you're like me, lately my Twitter Echo chamber was a lot about TurboRepo. Again, it's just my echo chamber, but still, I wanted to read a bit more about it.

After reading the docs, the comparisons posts and listened to a couple of podcast episodes about it, I thought I should give it a try.

One of the main competitors is Nx. I did try that in the past a few times, so I have some sort of reference for comparison in mind. Again, this is by no means a full comparison, but purely my thoughts on this.

Previous Experience with Nx

My day-to-day job revolves around Angular. I'm working on multiple projects, different sizes. Some of them are monorepos, some are simple CRUD applications.

Now, when Nx came into picture, I thought this is going to be life changing, especially for big projects, so, being a developer, I tried to add it everywhere 😅.

For some projects it was very straight forward, for some it was very tedious. The bigger the project, the more "specialised" the setup, the more difficult was to add.

Then, computational caching was added, and the speed of build times was insane. Insanely fast that is ⚡️. Again, this for the projects where I managed to add it. The dependency graph, the constraints of dependencies, the build times, the update process. All of it was great.

Now, for the half empty side. There were project where I simply failed to add it successfully. Sometimes I would struggle for days to make it work without success. Sometimes I would manage to make it work, but then, when I would want to update to a new version of Angular, the whole setup would collapse and nothing would work anymore. I do find the tool very powerful, but I compare it in my head a bit with Webpack. If it works out of the box, it's awesome. If you have to start fiddling with the config to make it work, the difficulty grows exponentially.

Again, this is simply my experience, there's a very valid explanation that I fail to understand it and therefor am not capable of setting it up properly. We're always learning 🤓.


With this experience in mind, I was thinking about where Turborepo would fit. I started adding it to repos where NX did not work out.

I'm fine with the lack of functionality in exchange for easier setup process. I'm aware that this simplicity in config will change in time, as features get added to the tool, but we'll cross that bridge when we get there.

Turborepo setup

The docs are pretty straightforward on this one. First, install turborepo:

npm install turbo -D

Then, create a turbo.json file in your root folder. This is the template:

"$schema": "",
"pipeline": {
"build": {
// A package's build script depends on that package's
// dependencies' and devDependencies'
// build tasks being completed first
// (the ^ symbol signifies upstream).
"dependsOn": ["^build"],
// note: output globs are relative to each package's package.json
// (and not the monorepo root)
"outputs": [".next/**"]
"test": {
// A package's test script depends on that package's
// own build script being completed first.
"dependsOn": ["build"],
"outputs": [],
// A package's test script should only be rerun when
// either a .tsx or .ts file has changed in src or test folders.
"inputs": ["src/**/*.tsx", "src/**/*.ts", "test/**/*.ts", "test/**/*.tsx"]
"lint": {
// A package's lint script has no dependencies and
// can be run whenever. It also has no filesystem outputs.
"outputs": []
"deploy": {
// A package's deploy script depends on the build,
// test, and lint scripts of the same package
// being completed. It also has no filesystem outputs.
"dependsOn": ["build", "test", "lint"],
"outputs": []

Next, add .turbo to your .gitignore file. For me, without doing this, caching would not work. It only started working after I did this. I'm guessing it uses the git history to figure out what changed. Good thing is that it is all part of the official docs.

Last step is to proxy your commands through turbo. Basically, the root package.json will have commands that will ask turborepo to find underlying commands and orchestrate them as efficiently as possible. Something like this:

"scripts": {
"build": "turbo run build",
"test": "turbo run test",
"lint": "turbo run lint",
"format:check": "turbo run format:check"

Turborepo advantages

Here are some advantages for my use-case:

  • It's easy to setup
  • It does not get intertwined with the rest of your configuration(eslint, prettier, angular, jest)
  • This also means that it's super easy to remove
  • Updating underlying tools/frameworks has 0 impact on the setup(for example updating angular)

I like this because it does not tie me down to the tool if something better comes along.

Want more?

If you want to know more about this, or something doesn't make any sense, please let me know.

Also, if you have questions, you know where to find me… On the internet!

Be kind to each other! 🧡

Over and out

My Twitter avatar
Catalin Ciubotaru 🚀

Since there’s a lot of talk in my Echo Chamber about @turborepo I decided to try it out and write my findings about it. This is by no means an exhaustive comparison or a tutorial, just how Turbo fits in my day-to-day, a regular Angular Developer. #Turborepo #Monorepo #Nx

Jul 30, 2022
12 people are talking about this

Wanna read more?

Updates delivered to your inbox!

A periodic update about my life, recent blog posts, how-tos, and discoveries.

No spam - unsubscribe at any time!