快速了解 Turborepo ,即刻上手使用

126 阅读10分钟

一、Turborepo 简介

Turborepo(简称 Turbo)是由 Vercel 推出的一款 高性能 Monorepo 构建系统,专注于优化 JavaScript / TypeScript 代码库的任务执行效率,核心解决 Monorepo 规模化过程中出现的“构建慢、调度乱、缓存差”三大痛点。它并非替代 pnpm、npm 等包管理器,而是作为“任务调度与缓存层”,与现有包管理器协同工作,兼容所有基于 npm 生态的项目结构。

exported_image (13).png

Turborepo 的核心优势在于 轻量、高效、易集成——无需大幅改造现有项目,只需添加一个 turbo.json 配置文件,就能复用项目已有的 package.json 脚本,快速实现任务的并行执行、增量构建与缓存复用,适配从个人项目到大型企业级工程的全场景需求。

Turborepo 的核心定位是“让 Monorepo 可规模化”:它通过智能的任务调度、精准的缓存机制,解决了 Monorepo 随着子包/应用增多而出现的构建耗时激增、任务依赖混乱等问题,让开发者无需关注任务执行顺序与重复构建,专注于代码开发本身。

exported_image (14).png

Turborepo 核心特性与优势

exported_image (15).png

  • 智能任务调度 + 极致构建效率:自动分析子包/应用间的依赖关系,按依赖顺序执行任务(如先构建被依赖的共享包,再构建应用),同时对无依赖任务并行执行,最大化利用机器多核性能;搭配增量与缓存复用核心能力,缓存每个任务的输入(源码、配置文件)与输出(构建产物、日志),输入未变时直接复用缓存,可将构建时间从几分钟缩短至秒级、毫秒级,据统计能减少 40%-85% 的月度构建时间,彻底解决 Monorepo 构建慢的痛点。
  • 零侵入集成 + 低上手成本:无需修改现有项目的代码结构,仅需配置 turbo.json,即可复用项目已有的 package.json 脚本(如 dev、build、lint);支持 pnpm、npm、yarn 等所有主流包管理器,几分钟内就能完成集成,上手门槛低,个人与团队均可快速适配,无需额外改造成本。
  • 任务精细化控制 + 场景适配性强:可通过配置精准控制每个任务的输入、输出、依赖关系,支持按子包过滤执行任务,也能全局执行所有任务,灵活适配本地开发、CI/CD 部署等不同场景;同时兼容所有 JavaScript/TypeScript 项目,适配 Vue、React、Next.js 等各类框架,兼容性极强。
  • 远程缓存共享 + 高效团队协作:支持将缓存同步到远程(如 Vercel 官方远程缓存、自建缓存),实现团队成员、CI/CD 环境共享同一套缓存,避免重复构建,大幅减少团队重复工作,降低协作成本,尤其适合团队协作场景。
  • 交互式终端 UI + 便捷开发体验:Turborepo 2.0 及以上版本提供稳定的终端 UI,可通过键盘操作切换查看单个任务日志,解决多任务并行时日志混乱的问题;同时支持 Jest 测试、数据库迁移等交互式任务的输入交互,进一步提升开发体验。
  • 轻量灵活 + 低复杂度负担:核心仅聚焦任务调度与缓存两大核心能力,不额外增加项目复杂度,可根据需求增量使用,也能与其他 Monorepo 工具配合使用,适配不同规模的项目(从个人小项目到大型企业级工程)。

二、Turborepo 快速上手(基于 pnpm Monorepo)

方式 1:新建 Turborepo 项目(从零开始最省心)

如果还没有项目,直接用 Turbo 官方脚手架新建,会自动生成标准的 Monorepo 结构,自带 turbo.json 基础配置,不用手动折腾。

  1. 执行新建命令:

    pnpm create turbo@latest
    

执行后会出现交互选项,按提示选择:

  • 输入项目名称(比如 my-turbo-monorepo
  • 选择包管理器(选 pnpm

目录结构参考:

my-monorepo/                  # Monorepo 根目录
├── apps/                      # 应用目录
│   ├── web/                   # 前台应用(有 dev/build/lint/clean 脚本)
│   └── admin/                 # 管理后台应用(同上)
├── packages/                  # 共享包目录
│   ├── ui/                    # 共享组件库(有 build/lint/clean 脚本)
│   └── utils/                 # 共享工具库(同上)
├── turbo.json                 # 新增:Turborepo 核心配置
├── pnpm-workspace.yaml        # 原有:pnpm workspace 配置
├── package.json               # 原有:全局依赖与脚本(新增 Turborepo 脚本)
└── .gitignore                 # 原有:新增 Turborepo 缓存忽略

方式 2:将已有普通项目(非 Monorepo)改造

如果你的项目是单一应用(没有多包结构),想接入 Turbo 提升构建效率,步骤也很简单,核心是搭建基础 Monorepo 结构 + 配置 Turbo。

  1. 先按 方式1 创建 Turborepo 项目

  2. 将现有项目移动到 apps目录下(Turbo 约定 apps 放应用,packages 放共享包),新建基础目录结构:

  3. 初始化 pnpm Monorepo(确保根目录有 pnpm-workspace.yaml):

    # 根目录执行,初始化 workspace
    pnpm init -y
    

方式 3:已有 Monorepo 项目改造为 Turborepo

1. 前置准备

确保你的 Monorepo 已经有完整结构:包含 apps(应用目录)、packages(共享包目录),且每个子包 / 应用的 package.json 中,已经配置了基础脚本(devbuildlint 等)——Turbo 会直接复用这些脚本,不用重新写。

2. 安装 Turborepo

在 Monorepo 根目录 执行命令,将 Turborepo 安装为全局开发依赖(-w 表示安装到工作区根目录,所有子包都能共用):

# 安装 Turborepo(pnpm 方式,npm/yarn 替换对应命令即可)
pnpm add turbo -D -w
​
# 验证安装成功(显示版本号即正常)
pnpm turbo --version

3. 核心配置:turbo.json

在 Monorepo 根目录创建 turbo.json 文件,这是 Turborepo 的「核心配置文件」,用来定义任务流水线、缓存规则、依赖关系等。以下是通用配置(适配 Vue/React/Next.js 项目,可直接复制使用,按需微调):

{
  "$schema": "https://turbo.build/schema.json",
  "ui": "tui",
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "inputs": [],
      "outputs": [
        "dist/**",
        ".next/**",
        "!.next/cache/**"
      ],
      "cache": true
    },
    "dev": {
      "dependsOn": ["^build"],
      "persistent": true,
      "cache": false
    },
    "lint": {
      "inputs": [
        "src/**/*.{ts,tsx,vue,js,jsx}",
        ".eslintrc",
        "package.json"
      ],
      "outputs": [],
      "cache": true
    },
    "clean": {
      "cache": false
    }
  }
}
关键配置说明(必看)
  • dependsOn: ["^build"] :最核心的依赖配置!^ 符号表示「所有被当前包依赖的包」。比如 apps/web 依赖 packages/ui,Turbo 会自动先执行 packages/uibuild 任务,再执行 apps/webbuild 任务,避免依赖未构建导致的报错。
  • inputs:定义「触发任务重新执行」的文件范围。只有 inputs 里的文件变了,Turbo 才会重新执行任务,否则直接复用缓存 —— 精准控制缓存,避免无效构建。
  • outputs:定义需要缓存的产物。任务执行完后,Turbo 会把这些文件 / 目录缓存起来,下次复用缓存时,直接恢复到对应位置,不用重新构建。
  • persistent: true:专门用于 devstart 这类长时运行的任务,标记后 Turbo 不会等待任务结束,还能支持交互式输入(比如 Jest 测试的交互操作)。

4. 优化根目录 package.json 脚本

在 Monorepo 根目录的 package.json 中,添加 Turbo 相关脚本,统一任务入口,不用每次都敲冗长的命令,简化执行流程:

{
  "name": "my-monorepo",
  "private": true,
  "packageManager": "pnpm@对应版本",
  "scripts": {
    "build": "turbo run build",
    "dev": "turbo run dev",
    "lint": "turbo run lint",
    "clean": "turbo run clean",
    "build:web": "turbo run build --filter=web",
    "build:admin": "turbo run build --filter=admin",
    "dev:web": "turbo run dev --filter=web",
    "dev:admin": "turbo run dev --filter=admin",
    "lint:fix": "turbo run lint -- --fix"
  },
  "devDependencies": {
    "turbo": "^2.0.0"
  }
}

关键说明--filter=<包名> 是 Turbo 的核心过滤命令,用来指定只对某个子包 / 应用执行任务,和 pnpm 的 -F 命令效果一致,精准控制任务范围,避免不必要的执行。

5. 确保子包 / 应用有对应脚本

Turbo 不会帮你写脚本,只会复用子包 / 应用自身 package.json 中的脚本。所以每个 apps 下的应用(如 webadmin)和 packages 下的共享包(如 uiutils),都必须有和 turbo.json 中定义的任务同名的脚本(devbuildlintclean 等)。

示例 1:apps/web/package.json(Vue + Vite 应用)

{
  "name": "web",
  "scripts": {
    "dev": "vite",
    "build": "vue-tsc && vite build",
    "lint": "eslint . --ext .vue,.ts,.js",
    "clean": "rm -rf dist node_modules/.vite"
  }
}

示例 2:packages/ui/package.json(共享组件库)

{
  "name": "@my/ui",
  "scripts": {
    "build": "tsup src/index.ts --format esm,cjs",
    "lint": "eslint . --ext .ts,.vue",
    "clean": "rm -rf dist"
  }
}

6. 执行任务与验证

配置完成后,在 Monorepo 根目录执行以下命令,验证 Turbo 是否正常工作 —— 第一次执行会全量构建,第二次会复用缓存,速度会明显提升!

(1)全仓库构建(最常用)

pnpm build

执行效果

  • Turbo 会自动分析子包依赖关系,先构建被依赖的共享包(如 packages/ui),再并行构建所有应用(如 apps/webapps/admin)。
  • 第一次执行:缓存未命中,全量构建;第二次执行:缓存命中,直接复用产物,秒级完成。

(2)只构建单个应用

# 只构建 apps/web(两种命令等价,选一种即可)
pnpm build:web
pnpm turbo run build --filter web

(3)启动开发服务

# 并行启动所有应用的 dev 服务
pnpm dev
​
# 只启动 apps/web 的 dev 服务(开发时最常用)
pnpm dev:web

说明:启动 dev 服务时,Turbo 会先执行所有被依赖包的 build 任务,再启动当前应用的 dev 服务,确保依赖包已构建完成,避免报错。

(4)代码检查与清理

# 全仓库代码检查
pnpm lint
​
# 全仓库代码检查并自动修复
pnpm lint:fix
​
# 全仓库清理构建产物
pnpm clean

三、Turborepo 核心能力实操(高频使用)

1. 缓存相关操作(核心)

  • 强制重新构建(跳过缓存) :当缓存出现异常,或需要强制全量构建时,执行: pnpm build --force
  • 查看缓存详情:执行以下命令,查看缓存的具体信息(如缓存键、缓存路径): pnpm turbo cache status
  • 清除本地缓存:清除本地所有缓存,适用于缓存污染场景: pnpm turbo cache prune

2. 任务依赖图查看

查看所有子包/应用的任务依赖关系,生成可视化图表(可在浏览器打开):

pnpm turbo build --graph

用途:快速排查任务执行顺序错乱的问题,清晰看到子包之间的依赖关系。

3. 只构建变更包(CI/CD 常用)

在 CI/CD 环境中,通常只需构建自上次提交以来发生变化的包,减少构建时间:

# 只构建自 main 分支以来修改的包
pnpm turbo build --affected --filter=apps/*

说明:--affected 表示“只处理变更的包”,--filter=apps/* 表示只过滤 apps 目录下的应用。

4. 远程缓存配置(团队/CI 必备)

远程缓存可实现团队成员、CI/CD 环境共享缓存,避免每个人/每个 CI 任务都重复构建,步骤如下:

# 1. 登录 Vercel(免费额度足够个人/中小团队使用)
pnpm turbo login
​
# 2. 链接当前 Monorepo 到 Vercel 远程缓存
pnpm turbo link

链接成功后,团队所有成员执行任务时,都会自动拉取/推送远程缓存,第二次构建几乎秒完。若需自建远程缓存,可参考 Turborepo 官方文档配置。

七、常见问题与解决方案

  • Q1:修改共享包后,应用 dev 服务未同步更新?

    解决方案:

    • 确保共享包(如 packages/ui)配置了 build 脚本,且 dev 任务配置了 "dependsOn": ["^build"]
    • 修改共享包后,重启应用的 dev 服务,或手动执行 pnpm build --filter=ui 重新构建共享包。
  • Q2:缓存失效或缓存污染,明明没改代码却重新构建?

    解决方案:

    • 检查 turbo.json 中 inputs 配置,避免包含不必要的文件(如 node_modules、日志文件)。
    • 若环境变量影响构建结果,需在 turbo.json 中添加 env 配置,指定影响缓存的环境变量(如 NODE_ENV)。
    • 执行 pnpm turbo cache prune 清除本地缓存,重新构建。
  • Q3:CI 环境中无法命中远程缓存?

    解决方案:确保 CI 环境已登录 Vercel(通过 TURBO_TOKEN 环境变量配置),且链接了当前项目,具体可参考 Turborepo 官方 CI 配置文档。