DEV Community

Cover image for Advanced monorepo management with Turborepo 2.0
Megan Lee for LogRocket

Posted on • Originally published at blog.logrocket.com

Advanced monorepo management with Turborepo 2.0

Written by Gapur Kassym✏️

We all start our first steps in software engineering with small projects. Over time, our projects become larger and more complex. This is where the new architecture of the monorepo project comes into play. There are many tools for developing monorepo projects but in this guide, we will focus on Turborepo and its recent v2 release.

New features in Turborepo 2.0

Turborepo, developed by Vercel, is a popular tool for creating monorepos in the JavaScript/Typescript ecosystem. It is powerful, fast, and easy to use, whether you want to install it or add it to an existing project.

If you are new to Turborepo and want a deeper dive, check out LogRocket’s guide to building a full-stack TypeScript application with Turborepo.

Recently, the Turborepo team introduced new core features in version 2.0. These features include:

  • A new terminal UI that enhances productivity and development speed with interactive tasks and clearer logs
  • Watch Mode, a dependency-aware task observer for any tool in your monorepo project
  • All-new documentation that offers comprehensive information about monorepository concepts, API references, and tool guides

New terminal UI

In previous versions of Turborepo, when we were working on both libraries and apps simultaneously, we had to read a large amount of log information in one place. Now, starting with version 2.0, we can select specific tasks — whether for a library or an app — and explore their logs individually. This makes it easier to focus and read.

Additionally, in previous versions of Turborepo, we could not interact with the script to execute commands, although many other monorepo tools allowed this. Now we can do this by typing to our scripts via stdin, and entering data directly into the interface. This allows us to run specific test suites using Jest, perform database migrations, and much more.

To make the task interactive, we can update the turbo.json file by adding "persistent": true for the specific task:

{
  "tasks": {
    "dev": {      
      "cache": false,      
      "persistent": true // add and make the task interactive
    }  
  }
}
Enter fullscreen mode Exit fullscreen mode

Then we can select the task in the terminal UI and press Enter to enter the task shell and CTRL+Z to exit.

Watch Mode

Turborepo can run many tasks at the same time, which helps us work faster. However, starting with version 2.0, we can get the most out of Turborepo's parallelization by using the "watcher" feature that allows us to re-run our code whenever we change something in our source code. Many tools don't do this or don't support monorepos, which leads to problems with scripts that depend on other scripts in our repository.

Let’s demonstrate how we can use it easily:

turbo watch dev lint test
Enter fullscreen mode Exit fullscreen mode

Now Turborepo will re-run tasks whenever we make changes to our code using the configuration from turbo.json.

All-new documentation

The Turborepo team has released updated documentation based on the strengths of previous versions and user feedback. They now offer:

  • Monorepo fundamentals and how-tos
  • Guides for integrating any tools with Turborepo
  • Architecture details and improved search

A dive into caching in Turborepo

One of the main reasons Turborepo stands out as a monorepo tool is its use of caching. Turborepo uses caching to speed up the development process and prevent doing the same work repeatedly. Turborepo caching saves a lot of time when working locally, and when combined with remote caching, it becomes even more powerful by sharing the cache across the entire team.

We can try to get our first cache by creating a Turborepo project with the following command:

npx create-turbo@latest // npm
pnpm dlx create-turbo@latest // pnpm
Enter fullscreen mode Exit fullscreen mode

Now, let’s run the build script in package.json, which triggers a turbo build:

 npm run build
Enter fullscreen mode Exit fullscreen mode

This will result in a cache miss because we have never run the previous build script before with this input set in this repository: Cache Miss Result If we run turbo build again, we get the following result: Successful Cache Result

Remote caching with Turborepo

Turborepo stores the results of tasks in the .turbo/cache directory and can share the cache with our teammates and CI to speed up work.

To use it, we need to authenticate with our remote cache provider using the following command:

npx turbo login // npm
Enter fullscreen mode Exit fullscreen mode

Then, link the repository on our machine:

npx turbo link // npm
Enter fullscreen mode Exit fullscreen mode

Now, when we run a task, Turborepo will automatically send the task’s output to the remote cache. The next time the same task is run on any machine authentication with the remote cache, it will retrieve the cached result on the first run.

Creating a monorepo project with Turborepo 2.0

Now, to get a good understanding of the new features in Turborepo 2.0, let's create our first monorepo project using a basic starter example.

I will first create a monorepo project using Turborepo:

npx create-turbo@latest // npm
pnpm dlx create-turbo@latest // pnpm
Enter fullscreen mode Exit fullscreen mode

This will prompt us for our project name and to select the package manager we want to use: Creating New Turborepo Project And voilà, we have just created our monorepo project using Turborepo! Our project includes the following packages/apps:

  • docs: A documentation Next.js app example
  • web: A web Next.js app example
  • @repo/ui: React component library for web and docs apps
  • @repo/eslint-config: Common eslint configurations for libraries and apps
  • @repo/typescript-config: tsconfig.json for libraries and apps

Turborepo Project Structure Our turbo.json file is set up as follows:

{
  "$schema": "https://turbo.build/schema.json",
  "ui": "tui",
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "inputs": ["$TURBO_DEFAULT$", ".env*"],
      "outputs": [".next/**", "!.next/cache/**"]
    },
    "lint": {
      "dependsOn": ["^lint"]
    },
    "dev": {
      "cache": false,
      "persistent": true
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Above, we set a specific URL schema for our Turbo configuration. We also defined ui as tui to format the terminal UI. Then, we specified the build, lint, and dev tasks.

Next, we will run all apps with the following command:

pnpm run dev
Enter fullscreen mode Exit fullscreen mode

It runs dev scripts in all app package.json files and opens them in a new terminal with tasks: Turborepo Terminal Tasks As we see above, we have two tasks on the left side of the terminal, and task details on the main content of the terminal window. If we navigate to the local URL, we will see more output logs, details about web app states, requests, and more. By switching between tasks, we can examine each detail separately by task content. This is an incredibly useful feature and makes it easier to understand while we are working on a specific app or package.

Lastly, we are going to test the new Watch Mode feature in our Turborepo project. Let's run all of our tasks with the following command:

turbo watch dev lint
Enter fullscreen mode Exit fullscreen mode

Now, we can see all the tasks on the left sidebar. If we navigate to web#lint task, we can see lint run once: Running Turborepo Watch Mode If we change anything in the source code of the web app, the lint task will be re-run like turbo run: Re-Running Watch Mode This is a very useful feature to speed up our work.

Turborepo vs. Other monorepo tools

There are many tools available for working with monorepos, such as Lerna, Nx, and Bazel, each with its own strengths and weaknesses. Some are designed specifically for the frontend, backend, or both, while others excel in large projects or focus mainly on TypeScript.

But Turborepo stands out for its emphasis on speed, caching and parallelization, ease of use, and its efficiency when working with both small and large projects. It also has a large community of users. There are many reasons why you should use Turborepo, especially given the Turborepo 2.0 release.

Thanks for reading. I hope you found this piece useful. Happy coding!


Get set up with LogRocket's modern error tracking in minutes:

  1. Visit https://logrocket.com/signup/ to get an app ID.
  2. Install LogRocket via NPM or script tag. LogRocket.init() must be called client-side, not server-side.

NPM:

$ npm i --save logrocket 

// Code:

import LogRocket from 'logrocket'; 
LogRocket.init('app/id');
Enter fullscreen mode Exit fullscreen mode

Script Tag:

Add to your HTML:

<script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script>
<script>window.LogRocket && window.LogRocket.init('app/id');</script>
Enter fullscreen mode Exit fullscreen mode

3.(Optional) Install plugins for deeper integrations with your stack:

  • Redux middleware
  • ngrx middleware
  • Vuex plugin

Get started now

Top comments (0)