多仓库拆分在小团队里复制粘贴成本低,等代码量上来,依赖升级、跨包重构、构建时间都会成为瓶颈。Monorepo用一套仓库管多个前端应用和共享包,配合pnpm与Turborepo,可以把构建时间压到原来的十分之一。这篇文章整理Monorepo前端工程化的选型与落地细节。
Monorepo与多仓库:前端工程化选型对比
多仓库(Multi-Repo)的问题集中在三处:共享组件要发版才能引用,改一次组件要把发布流程走一遍;依赖版本不一致,两个应用锁的版本号不同,排查问题靠猜;构建不能复用,每个仓库独立装依赖、独立编译。Monorepo把共享包放在同一仓库里,用workspace协议直接引用源码,改动即时生效,同时统一版本管理,一次性升级公共依赖。
代价是仓库变大、单次clone变慢,权限粒度变粗。团队规模小、共享组件多、构建依赖强,选Monorepo收益明确;项目独立部署、团队边界清晰,多仓库更省心。
pnpm workspace配置:workspace协议与依赖提升
pnpm是Monorepo依赖管理的默认选择,靠content-addressable存储实现全局唯一缓存,磁盘占用远小于npm/yarn。根目录pnpm-workspace.yaml声明包范围:
# pnpm-workspace.yaml
packages:
- apps/*
- packages/*
在apps/web/package.json里依赖共享包时,用workspace协议,版本不写死:
// apps/web/package.json
"dependencies": {
"@repo/ui": "workspace:*",
"lodash": "^4.17.21"
}
workspace:*让pnpm把packages/ui链接进来,改动即时生效,无需发布。根目录配置.npmrc开启严格依赖提升:
shamefully-hoist=false
strict-peer-dependencies=true
这样每个包只能引用自己声明的依赖,防止幽灵依赖。安装时用–frozen-lockfile保证CI环境与本地一致。
Turborepo任务编排:增量构建与远程缓存
Monorepo构建加速的核心是任务编排和缓存。Turborepo识别任务的依赖图,用内容哈希判断哪些包没变,命中缓存直接跳过构建。turbo.json里声明任务流水线:
{
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**"]
},
"test": {
"dependsOn": ["build"]
}
}
}
^build表示先构建依赖包再构建当前包;outputs声明产物目录,Turborepo据此缓存。远程缓存把缓存上传云端,新机器和CI直接拉取,本地没构建过也能秒级出结果。
Monorepo落地配套:lint、环境变量与发布节奏
落地时处理三个配套问题:第一,lint与类型检查编排进turbo任务(lint、typecheck放build之前),保证每个包通过统一门禁;第二,环境变量按应用读取.env,共享包不做环境注入,避免跨应用泄漏;第三,包发布节奏:只有packages下的共享库需要发布npm,apps直接部署,用changesets管理版本。
边界还有一个原则:不要把所有代码塞进Monorepo,把各自独立发布、很少联动的包留在外部仓库,让Monorepo管真正频繁联动的部分。依赖粒度与任务编排设计好了,Monorepo的收益远大于维护成本。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/qian-duan-monorepo-gong-cheng-hua-shi-zhan-pnpmworkspace-yu/