Bỏ qua để vào nội dung chính
Turborepo Monorepo Guide: Organize Your Frontend Projects at Scale

Turborepo Monorepo Guide: Organize Your Frontend Projects at Scale

Bởi Olivia Reed
26 thg 3, 20267 phút đọc

Turborepo's intelligent caching makes monorepos fast. Learn to set up a Turborepo workspace with shared packages, understand task graphs, and optimize CI build times.

Why Turborepo for Monorepos

A monorepo puts multiple projects in one repository — your app, a shared UI component library, utility packages, and internal tools. Without intelligent caching, every CI run rebuilds everything. Turborepo's content-aware caching means unchanged packages are never rebuilt — dramatically cutting CI times from 10+ minutes to under 2.

Initial Setup

npx create-turbo@latest my-monorepo
cd my-monorepo

This creates a workspace with example apps and packages. The structure:

my-monorepo/
  apps/
    web/          # Your Next.js app
    docs/         # Documentation site
  packages/
    ui/           # Shared React components
    config-ts/    # Shared tsconfig
    config-eslint/ # Shared ESLint config
  package.json    # Root workspace config
  turbo.json      # Pipeline definition
  pnpm-workspace.yaml

Defining the Pipeline in turbo.json

// turbo.json
{
  "$schema": "https://turbo.build/schema.json",
  "ui": "tui",
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "inputs": ["$TURBO_DEFAULT$", ".env.local"],
      "outputs": [".next/**", "!.next/cache/**", "dist/**"]
    },
    "test": {
      "dependsOn": ["^build"],
      "inputs": ["src/**", "tests/**", "vitest.config.*"]
    },
    "lint": {
      "inputs": ["src/**", "*.json"]
    },
    "typecheck": {
      "dependsOn": ["^build"]
    },
    "dev": {
      "cache": false,
      "persistent": true
    }
  }
}

Creating a Shared UI Package

// packages/ui/package.json
{
  "name": "@repo/ui",
  "version": "0.0.0",
  "private": true,
  "exports": {
    ".": "./src/index.ts",
    "./button": "./src/button.tsx",
    "./card": "./src/card.tsx"
  },
  "devDependencies": {
    "@repo/config-ts": "workspace:*",
    "typescript": "^5.4.2"
  },
  "peerDependencies": {
    "react": "^19.0.0"
  }
}
// packages/ui/src/button.tsx
import { type ButtonHTMLAttributes } from 'react';

interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
  variant?: 'primary' | 'secondary' | 'ghost';
  size?: 'sm' | 'md' | 'lg';
}

export function Button({ variant = 'primary', size = 'md', className = '', ...props }: ButtonProps) {
  const variants = {
    primary: 'bg-blue-600 text-white hover:bg-blue-700',
    secondary: 'bg-gray-100 text-gray-900 hover:bg-gray-200',
    ghost: 'hover:bg-gray-100 text-gray-700',
  };
  const sizes = { sm: 'px-3 py-1.5 text-sm', md: 'px-4 py-2', lg: 'px-6 py-3 text-lg' };
  return (
    <button
      className={`rounded-lg font-medium transition-colors ${variants[variant]} ${sizes[size]} ${className}`}
      {...props}
    />
  );
}

Using the Shared Package in an App

// apps/web/package.json — add dependency
{
  "dependencies": {
    "@repo/ui": "workspace:*"
  }
}

// apps/web/src/app/page.tsx
import { Button } from '@repo/ui/button';

export default function HomePage() {
  return <Button variant="primary">Get Started</Button>;
}

Remote Caching for CI

# Connect to Vercel Remote Cache (free for personal use)
npx turbo login
npx turbo link

# CI workflow with cache
- run: pnpm turbo build --team=your-team
  env:
    TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
    TURBO_TEAM: your-team

With remote caching, the second CI run of unchanged code completes in seconds rather than minutes — the cache is shared across all developers and CI machines.

Không spam, hủy đăng ký bất kỳ lúc nào.

Bài viết liên quan