关于 turborepo
这是一项介绍如何用 Turborepo 构建和管理 JavaScript、TypeScript 单体仓库的技能,涵盖任务编排、缓存、工作区配置与 CI 流程,适合维护多包仓库的开发者。
主要功能
- 01配置依赖感知的任务流水线
- 02使用本地与远程缓存
- 03按包或变更筛选任务
- 04精简部署所需的工作区
- 05设置工作区包
适用场景
- 01加快重复的单体仓库构建
- 02仅对变更包运行 CI 任务
- 03准备应用专用的 Docker 构建输入
- 04协调构建、测试与 lint 任务
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ timelessco/ recollect --skill turborepo安装后在 Claude Code 中输入/turborepo确认已加载。
详细介绍
Turborepo 技能
Turborepo 是一款高性能构建系统,针对 JavaScript 和 TypeScript 单体仓库进行了优化,使用 Rust 编写。它提供智能缓存、任务编排和远程执行功能,可大幅加快开发工作流。
参考
https://turborepo.com/llms.txt
何时使用此技能
在以下情况下使用此技能:
- 使用多个包搭建新的单体仓库
- 优化现有单体仓库的构建性能
- 实现跨包的任务流水线
- 配置智能缓存策略
- 为团队设置远程缓存
- 根据依赖关系编排任务
- 将单体仓库集成到 CI/CD 流水线中
- 从 Lerna、Nx 或其他单体仓库工具迁移
- 构建微前端或共享库
- 管理工作区依赖
核心概念
1. 单体仓库架构
Turborepo 将代码组织到单个仓库内的多个包中:
- 根包:包含工作区配置
- 内部包:共享库、实用工具、配置
- 应用程序:前端应用、后端服务等
- 工作区:npm/yarn/pnpm 工作区配置
2. 任务流水线
任务按依赖关系图组织:
- 任务依赖:定义执行顺序(先构建,再测试)
- 包依赖:遵循内部包之间的关系
- 并行执行:同时运行互不依赖的任务
- 拓扑排序:按正确的依赖顺序执行任务
3. 智能缓存
Turborepo 根据输入缓存任务输出:
- 本地缓存:在本地计算机上存储输出
- 远程缓存:在团队和 CI 之间共享缓存(Vercel 或自定义方案)
- 基于内容的哈希:仅在输入变更时重新运行
- 缓存恢复:从缓存中即时完成任务
4. 任务输出
定义要缓存的内容:
- 构建产物(dist/、build/)
- 测试结果
- 生成的文件
- 类型定义
安装
先决条件
# Requires Node.js 18+ and a package manager
node --version # v18.0.0+
全局安装
# npm
npm install turbo --global
# yarn
yarn global add turbo
# pnpm
pnpm add turbo --global
# bun
bun add turbo --global
按项目安装
# npm
npm install turbo --save-dev
# yarn
yarn add turbo --dev
# pnpm
pnpm add turbo --save-dev
# bun
bun add turbo --dev
项目设置
创建新的单体仓库
使用官方示例:
npx create-turbo@latest
交互式提示会询问:
- 项目名称
- 包管理器(npm/yarn/pnpm/bun)
- 示例模板选择
手动设置
1. 初始化工作区:
// package.json (root)
{
"name": "my-turborepo",
"private": true,
"workspaces": ["apps/*", "packages/*"],
"scripts": {
"build": "turbo run build",
"dev": "turbo run dev",
"test": "turbo run test",
"lint": "turbo run lint"
},
"devDependencies": {
"turbo": "latest"
}
}
2. 创建目录结构:
my-turborepo/
├── apps/
│ ├── web/ # Next.js app
│ └── docs/ # Documentation site
├── packages/
│ ├── ui/ # Shared UI components
│ ├── config/ # Shared configs (ESLint, TS)
│ └── tsconfig/ # Shared TypeScript configs
├── turbo.json # Turborepo configuration
└── package.json # Root package.json
3. 创建 turbo.json:
{
"$schema": "https://turbo.build/schema.json",
"globalDependencies": ["**/.env.*local"],
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": [".next/**", "!.next/cache/**", "dist/**"]
},
"dev": {
"cache": false,
"persistent": true
},
"lint": {},
"test": {
"dependsOn": ["build"]
}
}
}
配置(turbo.json)
基本结构
{
"$schema": "https://turbo.build/schema.json",
"globalDependencies": [".env", "tsconfig.json"],
"globalEnv": ["NODE_ENV"],
"pipeline": {
// Task definitions
}
}
流水线配置
具有依赖关系的任务:
{
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**", ".next/**"],
"env": ["NODE_ENV", "API_URL"]
}
}
}
关键属性:
dependsOn:先运行的任务["^build"]:先运行依赖项的构建任务["build"]:先运行自身的构建任务["^build", "lint"]:运行依赖项的构建任务和自身的 lint 任务
outputs:要缓存的文件/目录inputs:覆盖输入检测(默认:所有已跟踪文件)cache:启用/禁用缓存(默认:true)env:会影响输出的环境变量persistent:保持任务运行(适用于开发服务器)outputMode:控制输出显示方式
任务依赖模式
拓扑排序(^):
{
"build": {
"dependsOn": ["^build"] // Run dependencies' build first
}
}
常规:
{
"deploy": {
"dependsOn": ["build", "test"] // Run own build and test first
}
}
组合:
{
"test": {
"dependsOn": ["^build", "lint"] // Deps' build, then own lint
}
}
输出模式
{
"pipeline": {
"build": {
"outputMode": "full" // Show all output
},
"dev": {
"outputMode": "hash-only" // Show cache hash only
},
"test": {
"outputMode": "new-only" // Show new output only
},
"lint": {
"outputMode": "errors-only" // Show errors only
}
}
}
环境变量
全局环境变量:
{
"globalEnv": ["NODE_ENV", "CI"],
"globalDependencies": [".env", ".env.local"]
}
单任务环境变量:
{
"pipeline": {
"build": {
"env": ["NEXT_PUBLIC_API_URL", "DATABASE_URL"],
"passThroughEnv": ["CUSTOM_VAR"] // Pass without hashing
}
}
}
命令
turbo run
在各个包中运行任务:
# Run build in all packages
turbo run build
# Run multiple tasks
turbo run build test lint
# Run in specific packages
turbo run build --filter=web
turbo run build --filter=@myorg/ui
# Run in packages matching pattern
turbo run build --filter='./apps/*'
# Force execution (skip cache)
turbo run build --force
# Run from specific directory
turbo run build --filter='[./apps/web]'
# Run with dependencies
turbo run build --filter='...^web'
# Parallel execution control
turbo run build --concurrency=3
turbo run build --concurrency=50%
# Continue on error
turbo run test --continue
# Dry run
turbo run build --dry-run
# Output control
turbo run build --output-logs=new-only
turbo run build --output-logs=hash-only
turbo run build --output-logs=errors-only
turbo run build --output-logs=full
turbo prune
创建单体仓库的子集:
# Prune for specific app
turbo prune --scope=web
# Prune with Docker
turbo prune --scope=api --docker
# Output to custom directory
turbo prune --scope=web --out-dir=./deploy
使用场景:
- Docker 构建(仅包含必要的包)
- 部署特定应用
- 减小 CI/CD 上下文大小
turbo gen
在单体仓库中生成代码:
# Generate new package
turbo gen workspace
# Generate from custom generator
turbo gen my-generator
# List available generators
turbo gen --list
turbo link
将本地仓库连接到远程缓存:
# Link to Vercel
turbo link
# Unlink
turbo unlink
turbo login
通过 Vercel 进行身份验证:
turbo login
turbo ls
列出单体仓库中的包:
# List all packages
turbo ls
# JSON output
turbo ls --json
筛选
按包名称筛选
# Single package
turbo run build --filter=web
# Multiple packages
turbo run build --filter=web --filter=api
# Scoped package
turbo run build --filter=@myorg/ui
按模式筛选
# All apps
turbo run build --filter='./apps/*'
# Pattern matching
turbo run build --filter='*-ui'
按目录筛选
# From specific directory
turbo run build --filter='[./apps/web]'
按 Git 筛选
# Changed since main
turbo run build --filter='[main]'
# Changed since HEAD~1
turbo run build --filter='[HEAD~1]'
# Changed in working directory
turbo run test --filter='...[HEAD]'
按依赖项筛选
# Package and its dependencies
turbo run build --filter='...web'
# Package's dependencies only
turbo run build --filter='...^web'
# Package and its dependents
turbo run test --filter='ui...'
# Package's dependents only
turbo run test --filter='^ui...'
缓存策略
本地缓存
默认启用,存储在 ./node_modules/.cache/turbo
缓存行为:
{
"pipeline": {
"build": {
"outputs": ["dist/**"], // Cache dist directory
"cache": true // Enable caching (default)
},
"dev": {
"cache": false // Disable for dev servers
}
}
}
清除缓存:
# Clear Turbo cache
rm -rf ./node_modules/.cache/turbo
# Or use turbo command
turbo run build --force # Skip cache for this run
远程缓存
在团队和 CI 之间共享缓存:
1. 关联到 Vercel(推荐):
turbo login
turbo link
2. 自定义远程缓存:
// .turbo/config.json
{
"teamid": "team_123",
"apiurl": "https://cache.example.com",
"token": "your-token"
}
优点:
- 在团队之间共享构建结果
- 加快 CI/CD
- 确保构建一致
- 降低计算成本
缓存签名
以下情况会使缓存失效:
- 源文件发生变化
- 依赖项发生变化
- 环境变量发生变化(如果已指定)
- 全局依赖项发生变化
- 任务配置发生变化
控制输入:
{
"pipeline": {
"build": {
"inputs": ["src/**/*.ts", "!src/**/*.test.ts"],
"env": ["NODE_ENV"]
}
}
}
工作区模式
软件包类型
1. 内部软件包(packages/*):
// packages/ui/package.json
{
"name": "@myorg/ui",
"version": "0.0.0",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"scripts": {
"build": "tsc",
"dev": "tsc --watch",
"lint": "eslint ."
}
}
2. 应用(apps/*):
// apps/web/package.json
{
"name": "web",
"version": "1.0.0",
"private": true,
"dependencies": {
"@myorg/ui": "*",
"next": "latest"
},
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
}
}
依赖管理
工作区协议(pnpm/yarn):
{
"dependencies": {
"@myorg/ui": "workspace:*"
}
}
版本协议(npm):
{
"dependencies": {
"@myorg/ui": "*"
}
}
共享配置
ESLint 配置软件包:
// packages/eslint-config/index.js
module.exports = {
extends: ["next", "prettier"],
rules: {
// shared rules
},
};
TypeScript 配置软件包:
// packages/tsconfig/base.json
{
"compilerOptions": {
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
}
}
用法:
// apps/web/tsconfig.json
{
"extends": "@myorg/tsconfig/base.json",
"compilerOptions": {
"jsx": "preserve"
}
}
CI/CD 集成
GitHub Actions
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 18
- name: Install dependencies
run: npm install
- name: Build
run: npx turbo run build
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
- name: Test
run: npx turbo run test
GitLab CI
image: node:18
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
- .turbo/
build:
stage: build
script:
- npm install
- npx turbo run build
variables:
TURBO_TOKEN: $TURBO_TOKEN
TURBO_TEAM: $TURBO_TEAM
Docker
FROM node:18-alpine AS base
# Prune workspace
FROM base AS builder
RUN npm install -g turbo
COPY . .
RUN turbo prune --scope=web --docker
# Install dependencies
FROM base AS installer
COPY --from=builder /app/out/json/ .
COPY --from=builder /app/out/package-lock.json ./package-lock.json
RUN npm install
# Build
COPY --from=builder /app/out/full/ .
RUN npx turbo run build --filter=web
# Runner
FROM base AS runner
COPY --from=installer /app/apps/web/.next/standalone ./
COPY --from=installer /app/apps/web/.next/static ./apps/web/.next/static
COPY --from=installer /app/apps/web/public ./apps/web/public
CMD node apps/web/server.js
优化提示
- 在 CI 中使用远程缓存:
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
- 缓存 node_modules:
- uses: actions/cache@v3
with:
path: node_modules
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
- 仅运行受影响的任务:
turbo run build test --filter='...[origin/main]'
框架集成
Next.js
// apps/web/package.json
{
"name": "web",
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
},
"dependencies": {
"next": "latest",
"react": "latest"
}
}
turbo.json:
{
"pipeline": {
"build": {
"outputs": [".next/**", "!.next/cache/**"]
},
"dev": {
"cache": false,
"persistent": true
}
}
}
Vite
{
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**"]
},
"dev": {
"cache": false,
"persistent": true
}
}
}
NuxtJS
{
"pipeline": {
"build": {
"outputs": [".output/**", ".nuxt/**"]
},
"dev": {
"cache": false,
"persistent": true
}
}
}
开发工具集成
TypeScript
{
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**", "*.tsbuildinfo"]
},
"typecheck": {
"dependsOn": ["^build"]
}
}
}
ESLint
{
"pipeline": {
"lint": {
"dependsOn": ["^build"],
"outputs": []
}
}
}
Jest / Vitest
{
"pipeline": {
"test": {
"dependsOn": ["build"],
"outputs": ["coverage/**"],
"cache": true
}
}
}
Prisma
{
"pipeline": {
"db:generate": {
"cache": false
},
"db:push": {
"cache": false
}
}
}
最佳实践
1. 规划单体仓库结构
my-monorepo/
├── apps/ # Applications
│ ├── web/ # Frontend app
│ ├── api/ # Backend API
│ └── docs/ # Documentation
├── packages/ # Shared packages
│ ├── ui/ # UI components
│ ├── config/ # Shared configs
│ ├── utils/ # Utilities
│ └── tsconfig/ # TS configs
├── tooling/ # Development tools
│ ├── eslint-config/
│ └── prettier-config/
└── turbo.json
2. 明确任务依赖关系
{
"pipeline": {
"build": {
"dependsOn": ["^build"]
},
"test": {
"dependsOn": ["build"]
},
"lint": {
"dependsOn": ["^build"]
},
"deploy": {
"dependsOn": ["build", "test", "lint"]
}
}
}
3. 优化缓存配置
- 缓存构建产物,而非源文件
- 将所有生成的文件包含在输出中
- 排除缓存目录(例如
.next/cache) - 对开发服务器禁用缓存
{
"pipeline": {
"build": {
"outputs": [
"dist/**",
".next/**",
"!.next/cache/**",
"storybook-static/**"
]
},
"dev": {
"cache": false,
"persistent": true
}
}
}
4. 明智地使用环境变量
{
"globalEnv": ["NODE_ENV", "CI"],
"pipeline": {
"build": {
"env": ["NEXT_PUBLIC_API_URL"],
"passThroughEnv": ["DEBUG"] // Don't affect cache
}
}
}
5. 利用远程缓存
- 为所有团队成员启用
- 在 CI/CD 中配置
- 显著缩短构建时间
- 对大型团队尤其有益
6. 有效使用筛选器
# Build only changed packages
turbo run build --filter='...[origin/main]'
# Build specific app with dependencies
turbo run build --filter='...web'
# Test only affected packages
turbo run test --filter='...[HEAD^1]'
7. 统一组织脚本
根目录 package.json:
{
"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"
}
}
8. 处理持久任务
{
"pipeline": {
"dev": {
"cache": false,
"persistent": true // Keeps running
}
}
}
常见模式
全栈应用
apps/
├── web/ # Next.js frontend
│ └── package.json
├── api/ # Express backend
│ └── package.json
└── mobile/ # React Native
└── package.json
packages/
├── ui/ # Shared UI components
├── database/ # Database client/migrations
├── types/ # Shared TypeScript types
└── config/ # Shared configs
共享组件库
packages/
├── ui/ # Component library
│ ├── src/
│ ├── package.json
│ └── tsconfig.json
└── ui-docs/ # Storybook
├── .storybook/
├── stories/
└── package.json
微前端
apps/
├── shell/ # Container app
├── dashboard/ # Dashboard MFE
└── settings/ # Settings MFE
packages/
├── shared-ui/ # Shared components
└── router/ # Routing logic
故障排除
缓存问题
问题:任务本应使用缓存却未使用
# Check what's causing cache miss
turbo run build --dry-run=json
# Force rebuild
turbo run build --force
# Clear cache
rm -rf ./node_modules/.cache/turbo
问题:缓存过大
# Limit cache size in turbo.json
{
"cacheDir": ".turbo",
"cacheSize": "50gb"
}
依赖问题
问题:找不到内部软件包
# Ensure workspace is set up correctly
npm install
# Check package names match
npm ls @myorg/ui
# Rebuild dependencies
turbo run build --filter='...web'
任务执行问题
问题:任务运行顺序错误
- 检查
dependsOn配置 - 对依赖任务使用
^task - 确认任务名称与 package.json 脚本匹配
问题:开发服务器无法启动
{
"pipeline": {
"dev": {
"cache": false,
"persistent": true // Add this
}
}
}
性能问题
问题:构建耗时过长
# Run with concurrency limit
turbo run build --concurrency=2
# Use filters to build less
turbo run build --filter='...[origin/main]'
# Check for unnecessary dependencies
turbo run build --dry-run
问题:远程缓存无法使用
# Verify authentication
turbo link
# Check environment variables
echo $TURBO_TOKEN
echo $TURBO_TEAM
# Test connection
turbo run build --output-logs=hash-only
迁移指南
从 Lerna 迁移
- 将 Lerna 替换为 Turborepo:
npm uninstall lerna
npm install turbo --save-dev
- 将 lerna.json 转换为 turbo.json:
{
"pipeline": {
"build": {
"dependsOn": ["^build"]
}
}
}
- 更新脚本:
{
"scripts": {
"build": "turbo run build",
"test": "turbo run test"
}
}
从 Nx 迁移
- 安装 Turborepo:
npm install turbo --save-dev
- 将 nx.json 转换为 turbo.json:
- 将 targetDefaults 映射到 pipeline
- 转换 dependsOn 语法
- 配置缓存
- 更新工作区配置
- 迁移 CI/CD 脚本
资源
- 文档:https://turbo.build/repo/docs
- 示例:https://github.com/vercel/turbo/tree/main/examples
- Discord:https://turbo.build/discord
- GitHub:https://github.com/vercel/turbo
实施清单
设置 Turborepo 时:
- 全局或按项目安装 Turborepo
- 设置工作区结构(apps/、packages/)
- 创建包含流水线配置的 turbo.json
- 定义任务依赖关系(build、test、lint)
- 为每项任务配置缓存输出
- 设置全局依赖项和环境变量
- 连接到远程缓存(Vercel 或自定义缓存)
- 配置 CI/CD 集成
- 为大型代码仓库添加筛选策略
- 为团队编写单体仓库结构文档
- 设置代码生成(turbo gen)
- 使用 turbo prune 配置 Docker 构建
- 在本地测试缓存行为
- 在 CI 中验证远程缓存
- 优化并发设置