Turborepo Monorepo 指南:管理多应用程序项目
包含多个应用程序和共享包的 Monorepos 现在是构建互连软件产品的公司的标准架构。 Vercel 收购的 Turborepo 提供了构建编排层,使 monorepos 变得实用——处理任务依赖性、缓存和跨数十个包的并行执行。
要点
- Turborepo 远程缓存可以将增量更改的 CI 构建时间缩短 80-90%
- 任务管道确保包自动按照正确的依赖顺序构建
- 共享包(类型、验证器、实用程序)消除了应用程序之间的代码重复
- pnpm 工作空间为 monorepos 提供磁盘高效的依赖管理
Monorepo 架构
目录结构
典型的 Turborepo monorepo 将应用程序与共享包分开:
my-monorepo/
apps/
api/ # NestJS backend
web/ # Next.js frontend
docs/ # Documentation site
mobile/ # React Native app
packages/
db/ # Drizzle ORM schemas and migrations
types/ # Shared TypeScript types
validators/ # Zod validation schemas
utils/ # Shared utility functions
ui/ # Shared UI components
config/ # Shared configuration (ESLint, TypeScript)
turbo.json # Turborepo configuration
pnpm-workspace.yaml
package.json # Root package.json
工作区配置
在 pnpm-workspace.yaml 中定义工作区:
packages:
- "apps/*"
- "packages/*"
每个工作区都有自己的 package.json 以及依赖项和脚本。使用工作区协议引用共享包:
{
"dependencies": {
"@myorg/types": "workspace:*",
"@myorg/validators": "workspace:*",
"@myorg/utils": "workspace:*"
}
}
Turborepo 配置
任务管道
Turbo.json 定义任务如何相互关联:
{
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**", ".next/**"]
},
"dev": {
"dependsOn": ["^build"],
"cache": false,
"persistent": true
},
"lint": {
"dependsOn": ["^build"]
},
"test": {
"dependsOn": ["build"]
}
}
}
关键概念:
- dependsOn: ["^build"]:插入符号 (^) 表示“首先构建所有依赖项”。构建 Web 应用程序时,Turborepo 首先构建包/类型、包/验证器和包/实用程序。
- 输出:Turborepo 缓存的文件。在后续运行中,如果输入未更改,Turborepo 将重播缓存的输出而不是重建。
- persistent: true:对于持续运行的开发服务器。
- cache: false:禁用必须始终运行的任务(如开发服务器)的缓存。
共享包
类型包
集中跨应用程序使用的 TypeScript 类型:
// packages/types/src/user.ts
export interface User {
id: string;
email: string;
name: string;
role: "admin" | "user" | "support";
createdAt: Date;
}
export type CreateUserDTO = Omit<User, "id" | "createdAt">;
export type UpdateUserDTO = Partial<CreateUserDTO>;
验证器包
Zod 模式在前端和后端之间共享:
// packages/validators/src/user.ts
import { z } from "zod";
export const createUserSchema = z.object({
email: z.string().email(),
name: z.string().min(2).max(255),
role: z.enum(["admin", "user", "support"]),
});
构建配置
共享包必须先预先构建,然后应用程序才能使用它们。使用将 TypeScript 编译为 JavaScript 的构建脚本配置每个包:
{
"scripts": {
"build": "tsc --project tsconfig.json",
"dev": "tsc --watch"
}
}
缓存策略
本地缓存
Turborepo 默认将任务输出缓存在 node_modules/.cache/turbo 中。当您运行turbo build并且没有任何变化时,Turborepo会在几毫秒内重播缓存的输出。
远程缓存
对于 CI/CD,启用远程缓存以在团队成员和 CI 运行之间共享构建工件:
npx turbo login
npx turbo link
远程缓存意味着在一台开发人员机器上完成的构建或 CI 运行可供每个人使用。影响是巨大的:增量 CI 构建时间从 10 分钟缩短到不到 1 分钟。
开发工作流程
运行所有应用程序
pnpm dev # Starts all apps and watches all packages
Turborepo 首先构建共享包(因为 dev 取决于 ^build),然后并行启动应用程序开发服务器。对共享包的更改会触发传播到使用应用程序的重建。
运行特定应用程序
pnpm dev --filter=web # Only the web app and its dependencies
pnpm dev --filter=api # Only the API and its dependencies
过滤对于大型单一存储库至关重要,因为不需要启动所有内容。
CI/CD 优化
受影响的包检测
Turborepo 确定自上次提交以来哪些包发生了更改,并且只为受影响的包运行任务:
turbo build --filter=...[HEAD^1]
这仅针对在最新提交及其依赖项中更改的包运行构建。
并行执行
Turborepo 并行运行独立任务。如果packages/types和packages/utils没有依赖关系,它们会同时构建。并发级别适应可用的 CPU 内核。
常见问题
问:Turborepo monorepo 可以处理多少个包裹?
Turborepo 处理包含数百个包的 monorepos。性能可以很好地扩展,因为任务图是在启动时进行分析的,而缓存意味着大多数包会跳过增量更改的构建。
问:我们应该在工作区中使用 pnpm 还是 npm?
强烈建议将 pnpm 用于 monorepos。其内容可寻址存储可消除软件包之间的重复依赖关系,从而节省大量磁盘空间和安装时间。 pnpm 工作区对于依赖项解析也更加严格,可以捕获丢失的依赖项声明。
问:我们如何跨应用程序处理不同的 Node.js 版本?
使用每个package.json中的engines字段来指定Node.js版本要求。对于运行时差异,请配置 CI 以使用每个应用程序的适当版本。
问:我们可以逐步采用 Turborepo 吗?
是的。将turbo.json 添加到现有的pnpm 工作区项目并配置任务管道。现有脚本继续有效。您无需重组即可立即获得缓存和任务编排。
下一步是什么
Turborepo 将 monorepo 开发从维护负担转变为生产力倍增器。从简单的结构开始,然后根据项目需求进行扩展。
联系 ECOSIRE 获取单一存储库架构咨询,或探索我们的 Odoo 集成服务 获取多应用 ERP 架构。
由 ECOSIRE 发布——帮助企业利用企业软件解决方案进行扩展。
作者
ECOSIRE TeamTechnical Writing
The ECOSIRE technical writing team covers Odoo ERP, Shopify eCommerce, AI agents, Power BI analytics, GoHighLevel automation, and enterprise software best practices. Our guides help businesses make informed technology decisions.
相关文章
使用 PostgreSQL 进行 Drizzle ORM:完整指南
使用 PostgreSQL 进行 Drizzle ORM 的完整指南:模式设计、迁移、类型安全查询、关系、事务和 TypeScript 应用程序的生产模式。
GitHub Actions Monorepo 项目的 CI/CD
Turborepo monorepos 的完整 GitHub Actions CI/CD 指南:仅受影响的构建、并行作业、缓存策略、基于环境的部署和安全最佳实践。
Power BI 部署管道:开发到生产工作流程
实施 Power BI 部署管道以进行受控开发 - 通过自动验证和回滚在开发、测试和生产阶段提升数据集和报告。