Turborepo: High-Performance Monorepo Build System
Master Turborepo for monorepo management. Learn workspace setup, caching, pipelines, and build performant multi-package JavaScript projects.
Moshiour Rahman
Advertisement
What is Turborepo?
Turborepo is a high-performance build system for JavaScript and TypeScript monorepos. It provides intelligent caching, parallel execution, and incremental builds to dramatically speed up development.
Key Features
| Feature | Description |
|---|---|
| Caching | Local and remote build caching |
| Parallelization | Run tasks concurrently |
| Incremental | Only rebuild what changed |
| Pipelines | Define task dependencies |
Getting Started
Create New Monorepo
# Create new Turborepo
npx create-turbo@latest my-monorepo
# Or with specific package manager
npx create-turbo@latest my-monorepo --package-manager pnpm
Add to Existing Project
# Install Turborepo
npm install turbo --save-dev
# Or globally
npm install turbo --global
Project Structure
my-monorepo/
├── apps/
│ ├── web/
│ │ ├── package.json
│ │ └── ...
│ └── docs/
│ ├── package.json
│ └── ...
├── packages/
│ ├── ui/
│ │ ├── package.json
│ │ └── ...
│ ├── config/
│ │ ├── eslint/
│ │ └── typescript/
│ └── utils/
│ ├── package.json
│ └── ...
├── package.json
├── turbo.json
└── pnpm-workspace.yaml
Configuration
turbo.json
{
"$schema": "https://turbo.build/schema.json",
"globalDependencies": ["**/.env.*local"],
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**", ".next/**", "!.next/cache/**"]
},
"lint": {
"dependsOn": ["^lint"]
},
"test": {
"dependsOn": ["build"],
"outputs": ["coverage/**"],
"inputs": ["src/**/*.tsx", "src/**/*.ts", "test/**/*.ts"]
},
"dev": {
"cache": false,
"persistent": true
},
"clean": {
"cache": false
}
}
}
Workspace Configuration
# pnpm-workspace.yaml
packages:
- 'apps/*'
- 'packages/*'
// package.json (npm/yarn workspaces)
{
"workspaces": [
"apps/*",
"packages/*"
]
}
Root package.json
{
"name": "my-monorepo",
"private": true,
"scripts": {
"build": "turbo run build",
"dev": "turbo run dev",
"lint": "turbo run lint",
"test": "turbo run test",
"clean": "turbo run clean && rm -rf node_modules"
},
"devDependencies": {
"turbo": "^1.10.0"
},
"packageManager": "pnpm@8.0.0"
}
Pipeline Configuration
Task Dependencies
{
"pipeline": {
// ^build means run build in dependencies first
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**"]
},
// Run lint after linting dependencies
"lint": {
"dependsOn": ["^lint"]
},
// Run test after build completes
"test": {
"dependsOn": ["build"]
},
// Deploy depends on build and test
"deploy": {
"dependsOn": ["build", "test", "lint"],
"outputs": []
}
}
}
Caching
{
"pipeline": {
"build": {
"dependsOn": ["^build"],
// Files that are outputs
"outputs": ["dist/**", ".next/**"],
// Files that affect cache
"inputs": [
"src/**",
"!src/**/*.test.ts"
]
},
"dev": {
// Never cache dev server
"cache": false,
// Keep running
"persistent": true
}
}
}
Environment Variables
{
"globalEnv": ["CI", "NODE_ENV"],
"pipeline": {
"build": {
"dependsOn": ["^build"],
"env": ["DATABASE_URL", "API_KEY"],
"outputs": ["dist/**"]
},
"test": {
"env": ["TEST_DATABASE_URL"],
"outputs": ["coverage/**"]
}
}
}
Running Tasks
Basic Commands
# Run build in all workspaces
turbo run build
# Run multiple tasks
turbo run build lint test
# Run in specific workspace
turbo run build --filter=web
# Run in workspace and dependencies
turbo run build --filter=web...
# Run in dependents only
turbo run build --filter=...ui
# Run with pattern matching
turbo run build --filter="@myorg/*"
turbo run build --filter="./apps/*"
Filtering
# By package name
turbo run build --filter=@myorg/web
# By directory
turbo run build --filter=./apps/web
# Include dependencies
turbo run build --filter=web...
# Include dependents
turbo run build --filter=...ui
# Changed packages (git)
turbo run build --filter=[HEAD^1]
# Combining filters
turbo run build --filter=...@myorg/ui --filter=@myorg/web
Parallel Execution
# Limit concurrency
turbo run build --concurrency=4
turbo run build --concurrency=50%
# Sequential execution
turbo run build --concurrency=1
# Continue on error
turbo run test --continue
Shared Packages
UI Package
// packages/ui/package.json
{
"name": "@myorg/ui",
"version": "0.0.1",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.js"
},
"./button": {
"import": "./dist/button.mjs",
"require": "./dist/button.js"
}
},
"scripts": {
"build": "tsup src/index.tsx --format cjs,esm --dts",
"dev": "tsup src/index.tsx --format cjs,esm --dts --watch",
"lint": "eslint src/"
},
"peerDependencies": {
"react": "^18.0.0"
}
}
// packages/ui/src/index.tsx
export * from './button';
export * from './card';
export * from './input';
Consuming Shared Packages
// apps/web/package.json
{
"name": "@myorg/web",
"dependencies": {
"@myorg/ui": "workspace:*",
"@myorg/utils": "workspace:*"
}
}
// apps/web/src/app.tsx
import { Button, Card } from '@myorg/ui';
import { formatDate } from '@myorg/utils';
export function App() {
return (
<Card>
<p>Today is {formatDate(new Date())}</p>
<Button>Click me</Button>
</Card>
);
}
Shared Configuration
TypeScript Config
// packages/config/typescript/base.json
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true
}
}
// packages/config/typescript/react.json
{
"extends": "./base.json",
"compilerOptions": {
"jsx": "react-jsx",
"lib": ["DOM", "DOM.Iterable", "ES2020"]
}
}
// apps/web/tsconfig.json
{
"extends": "@myorg/config/typescript/react.json",
"include": ["src"],
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}
}
ESLint Config
// packages/config/eslint/react.js
module.exports = {
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:react/recommended',
'plugin:react-hooks/recommended',
'prettier'
],
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint', 'react'],
settings: {
react: {
version: 'detect'
}
},
rules: {
'react/react-in-jsx-scope': 'off'
}
};
// apps/web/.eslintrc.js
module.exports = {
root: true,
extends: ['@myorg/config/eslint/react']
};
Remote Caching
Vercel Remote Cache
# Login to Vercel
turbo login
# Link to Vercel project
turbo link
# Run with remote cache
turbo run build
Self-Hosted Cache
// turbo.json
{
"remoteCache": {
"signature": true
}
}
# Set remote cache URL
export TURBO_API="https://cache.example.com"
export TURBO_TOKEN="your-token"
export TURBO_TEAM="your-team"
turbo run build
CI/CD Integration
GitHub Actions
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2
- uses: pnpm/action-setup@v2
with:
version: 8
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
- run: pnpm install
- run: pnpm turbo run build lint test
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
Affected Packages Only
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- run: pnpm install
# Only build changed packages
- run: pnpm turbo run build --filter=[HEAD^1]
Generator
Create Package Generator
# Install generator
turbo gen
// turbo/generators/config.ts
import type { PlopTypes } from '@turbo/gen';
export default function generator(plop: PlopTypes.NodePlopAPI) {
plop.setGenerator('package', {
description: 'Create a new package',
prompts: [
{
type: 'input',
name: 'name',
message: 'Package name'
}
],
actions: [
{
type: 'add',
path: 'packages/{{name}}/package.json',
templateFile: 'templates/package.json.hbs'
},
{
type: 'add',
path: 'packages/{{name}}/src/index.ts',
template: 'export const {{name}} = () => {};'
}
]
});
}
Summary
| Feature | Command |
|---|---|
| Build all | turbo run build |
| Filter | --filter=package-name |
| Parallel | --concurrency=N |
| Remote cache | turbo login && turbo link |
| Generate | turbo gen |
Turborepo provides fast, scalable monorepo tooling for JavaScript and TypeScript projects.
Advertisement
Moshiour Rahman
Software Architect & AI Engineer
Enterprise software architect with deep expertise in financial systems, distributed architecture, and AI-powered applications. Building large-scale systems at Fortune 500 companies. Specializing in LLM orchestration, multi-agent systems, and cloud-native solutions. I share battle-tested patterns from real enterprise projects.
Related Articles
React Hooks Complete Guide: useState to Custom Hooks
Master all React hooks from basics to advanced. Learn useState, useEffect, useContext, useReducer, useMemo, useCallback, and create custom hooks.
JavaScriptPlaywright: Modern End-to-End Testing Guide
Master Playwright for browser automation and testing. Learn selectors, assertions, API testing, visual testing, and build reliable E2E test suites.
JavaScriptTypeScript Advanced Guide: Types, Generics, and Patterns
Master advanced TypeScript concepts. Learn generics, utility types, conditional types, mapped types, and professional patterns for type-safe code.
Comments
Comments are powered by GitHub Discussions.
Configure Giscus at giscus.app to enable comments.