Supercharge Your Development with Turborepo: A Practical Guide

Supercharge Your Development with Turborepo: A Practical Guide
If you've ever worked on a project with multiple packages or apps, you know the pain: slow builds, inconsistent tooling, and the constant struggle to keep everything in sync. Turborepo solves these problems with an intelligent build system that makes monorepo management feel like a superpower.
In this guide, I'll walk you through setting up Turborepo and optimizing your workflow for maximum productivity.
What is Turborepo and Why Should You Care?
Turborepo is a high-performance build system for JavaScript and TypeScript codebases. It's designed to make monorepo management efficient through:
- ā” Incremental builds - Only rebuild what changed
- š Parallel execution - Run tasks across packages simultaneously
- š¾ Intelligent caching - Never rebuild the same code twice
- š Dependency graph - Understand relationships between packages
Whether you're a solo developer or part of a large team, Turborepo can dramatically improve your development experience.
Getting Started: Setting Up Your First Turborepo
Let's start with a fresh project. You can either create a new Turborepo from scratch or add it to an existing project.
Option 1: Create a New Turborepo
1# Using npx
2npx create-turbo@latest my-turborepo
3
4# Using yarn
5yarn create turbo my-turborepo
6
7# Using pnpm
8pnpm create turbo my-turborepo
This creates a starter monorepo with a sample structure that includes:
apps/
- Your applicationspackages/
- Shared packages/librariesturbo.json
- Turborepo configuration
Option 2: Add Turborepo to an Existing Project
If you already have a project, you can add Turborepo with:
1# Using npm
2npm install turbo --save-dev
3
4# Using yarn
5yarn add turbo --dev
6
7# Using pnpm
8pnpm add turbo --save-dev
Then create a turbo.json
file in your project root:
1{
2 "$schema": "https://turbo.build/schema.json",
3 "pipeline": {
4 "build": {
5 "dependsOn": ["^build"],
6 "outputs": ["dist/**", ".next/**"]
7 },
8 "lint": {
9 "outputs": []
10 },
11 "dev": {
12 "cache": false,
13 "persistent": true
14 }
15 }
16}
Understanding the Turborepo Configuration
The heart of Turborepo is the turbo.json
file, which defines your task pipeline. Let's break down the key components:
Pipeline Tasks
1"pipeline": {
2 "build": {
3 "dependsOn": ["^build"],
4 "outputs": ["dist/**", ".next/**"]
5 }
6}
This tells Turborepo:
- Run the
build
script in each package - Before building a package, build all its dependencies first (that's what
^build
means) - Cache the
dist/
and.next/
directories as outputs
Task Dependencies with dependsOn
The dependsOn
array defines prerequisites for a task:
["^build"]
- Runbuild
on all dependencies first["build"]
- Run thebuild
task in the same package first["$TASK_NAME"]
- Run a specific task in the same package first
Caching with outputs
The outputs
array tells Turborepo what files to cache:
["dist/**"]
- Cache everything in thedist/
directory[]
- Don't cache anything (good for linting or testing)
Practical Example: Setting Up a Full-Stack Monorepo
Let's set up a practical monorepo with a Next.js frontend and a shared UI library:
1my-turborepo/
2āāā apps/
3ā āāā web/ # Next.js app
4āāā packages/
5ā āāā ui/ # Shared UI components
6āāā package.json
7āāā turbo.json
1. Configure the Root package.json
1{
2 "name": "my-turborepo",
3 "private": true,
4 "workspaces": [
5 "apps/*",
6 "packages/*"
7 ],
8 "scripts": {
9 "build": "turbo run build",
10 "dev": "turbo run dev",
11 "lint": "turbo run lint",
12 "test": "turbo run test"
13 },
14 "devDependencies": {
15 "turbo": "latest"
16 }
17}
2. Configure turbo.json
1{
2 "$schema": "https://turbo.build/schema.json",
3 "pipeline": {
4 "build": {
5 "dependsOn": ["^build"],
6 "outputs": ["dist/**", ".next/**"]
7 },
8 "dev": {
9 "cache": false,
10 "persistent": true
11 },
12 "lint": {
13 "outputs": []
14 },
15 "test": {
16 "dependsOn": ["build"],
17 "outputs": [],
18 "inputs": ["src/**/*.tsx", "src/**/*.ts", "test/**/*.ts", "test/**/*.tsx"]
19 }
20 }
21}
3. Create the UI Package
In packages/ui/package.json
:
1{
2 "name": "ui",
3 "version": "0.0.0",
4 "main": "./dist/index.js",
5 "types": "./dist/index.d.ts",
6 "scripts": {
7 "build": "tsup src/index.tsx --format esm,cjs --dts --external react",
8 "dev": "tsup src/index.tsx --format esm,cjs --watch --dts --external react",
9 "lint": "eslint src/**/*.ts*",
10 "test": "jest"
11 },
12 "devDependencies": {
13 "tsup": "^6.5.0",
14 "typescript": "^4.9.4"
15 },
16 "peerDependencies": {
17 "react": "^18.2.0"
18 }
19}
4. Set Up the Next.js App
In apps/web/package.json
:
1{
2 "name": "web",
3 "version": "0.0.0",
4 "private": true,
5 "scripts": {
6 "dev": "next dev",
7 "build": "next build",
8 "start": "next start",
9 "lint": "next lint"
10 },
11 "dependencies": {
12 "next": "^13.1.1",
13 "react": "^18.2.0",
14 "react-dom": "^18.2.0",
15 "ui": "*"
16 },
17 "devDependencies": {
18 "@types/node": "^18.11.18",
19 "@types/react": "^18.0.26",
20 "typescript": "^4.9.4"
21 }
22}
Turborepo in Action: Running Tasks
Now that we have our monorepo set up, let's see how to run tasks:
Building Everything
1turbo run build
This builds all packages and apps in the correct order, with caching enabled.
Running Development Servers
1turbo run dev
This starts development servers for all packages and apps in parallel.
Filtering Tasks to Specific Packages
1# Build only the web app
2turbo run build --filter=web
3
4# Build the web app and its dependencies
5turbo run build --filter=web...
6
7# Build everything except the web app
8turbo run build --filter=!web
Advanced Features: Remote Caching
For team environments, Turborepo offers remote caching to share build artifacts across developers and CI/CD:
1# Login to Vercel (if using Vercel's remote cache)
2npx turbo login
3
4# Link your project
5npx turbo link
6
7# Run with remote caching enabled
8turbo run build --team="your-team"
Performance Tips and Best Practices
1. Optimize Your Task Dependencies
Be specific about task dependencies to avoid unnecessary work:
1"build": {
2 "dependsOn": ["^build", "test"],
3 "outputs": ["dist/**"]
4}
2. Use Pruning in CI
Turborepo can prune your workspace to only the packages affected by a change:
1turbo prune --scope=web
This creates a smaller subset of your monorepo containing only what's needed to build the specified package.
3. Leverage Environment Variables for Configuration
1# In your CI setup
2TURBO_TEAM="your-team" TURBO_TOKEN="xxx" turbo run build
4. Use Workspaces Wisely
Not everything needs to be a separate package. Group related functionality and avoid creating too many tiny packages.
When to Use Turborepo vs. Other Tools
Turborepo shines in these scenarios:
- šļø JavaScript/TypeScript monorepos with multiple apps/packages
- š Projects where build performance is critical
- š§© Teams working on related packages simultaneously
It might not be the best fit for:
- š Single-package projects with no shared code
- š Polyglot monorepos with many non-JS languages
Troubleshooting Common Issues
Caching Not Working
Check that:
- Your
outputs
are correctly specified - You're not modifying cached files during the build
- Environment variables are consistent
Tasks Running in the Wrong Order
Verify your dependsOn
configurations and ensure your dependency graph is correct.
Conclusion: Scaling Your Development with Turborepo
Turborepo transforms how you manage complex JavaScript projects by making builds faster, more reliable, and easier to reason about. Start with a simple configuration and gradually optimize as your project grows.
Key takeaways:
- š Turborepo dramatically speeds up builds through intelligent caching
- š¦ It works with any package manager (npm, yarn, pnpm)
- ļæ½ The pipeline configuration gives you fine-grained control
- š Remote caching enables team-wide performance benefits
Ready to try a specific command?
1# For most projects, start with:
2turbo run dev --filter=apps/web
For single-package projects:
1turbo run dev --filter=apps/web
š Single-package projects gain little from turbo dev due to lack of parallel tasks and caching.
Additional Resources
Turborepo empowers you to scale development smoothly, whether you're working solo or across dozens of teams. Start small. Scale fast.
Have you tried Turborepo in your projects? What performance improvements did you see? Let me know in the comments below!