pnpm monorepo 中管理依赖的最佳实践,与 Catalogs(目录)协议的使用(monorepo 中统一版本管理)
monorepo 中如何管理依赖?
在需要的 repo
中安装依赖
在多个 repo
中安装相同依赖,可以使用以下命令:
npm install jest --workspace=web --workspace=mobile --save-dev
yarn@v1:
yarn workspace web add jest --dev
yarn workspace mobile add jest --dev
yarn@v2
yarn workspaces foreach -R --from '{web,@repo/ui}' add jest --dev
pnpm install jest --save-dev --recursive --filter=web --filter=mobile
需要注意的是:不同的
包管理器
在选择依赖安装的node_modules
的位置不同(依赖提升
)
优势
- 可维护性: 每个
repo
中的package.json
都会声明需要的依赖,开发者可以更容易地理解和处理依赖。 - 灵活性: 在大型、复杂的
monorepo
中,保持相同版本的依赖是比较困难的。不同的repo
的迭代优先级不一致,比如web
和ui
需要升级react
版本,而web
可能仍在功能迭代中,ui
则可以提前发布相关变更。
简洁的根目录依赖
依赖管理参考
https://github.com/vercel/turborepo/tree/main
https://github.com/vuejs/core/tree/main
幽灵依赖
├── apps
│ ├── mobile (dependencies: {axios: '^1.7.7'})
│ └── web (dependencies: {lodash: '4.17.21'})
└── package.json
如何统一依赖版本?
- 使用 syncpack 、 manypkg 和 sherif 等工具
- 使用 pnpm Catalogs 协议
Catalogs
Catalogs 起初是在 Vite Conf 2023 中提出,于今年
7.8
号发布: pnpm@9.5,所以使用Catalogs
协议请保持你的pnpm
版本 >=9.5.0
优势
- 统一版本: 在一个
workspace
中,通常希望包之间的依赖可以使用同一个版本,使用Catalogs
可以更方便的维护版本统一性 - 减少升级工作量和代码合并冲突: 在升级或降级依赖项时,只需要操作
pnpm-workspace.yaml
而不是每个包的package.json
,可有效减少冲突的发生。
使用
支持协议的字段
dependencies
devDependencies
optionalDependencies
pnpm.overrides
默认 Catalog
packages:
- packages/*
# Define a catalog of version ranges.
catalog:
react: ^18.3.1
react-dom: ^18.3.1
{
"name": "@example/app",
"dependencies": {
"react": "catalog:",
// 或者
"react-dom": "catalog:default"
}
}
可命名的 Catalogs
catalog:
react: ^16.14.0
react-dom: ^16.14.0
catalogs:
# Can be referenced through "catalog:react17"
react17:
react: ^17.0.2
react-dom: ^17.0.2
# Can be referenced through "catalog:react18"
react18:
react: ^18.3.1
react-dom: ^18.3.1
{
"name": "@example/components",
"dependencies": {
// 使用 默认配置
"react": "catalog:",
// 使用 具名配置
"react-dom": "catalog:react18"
}
}
发布后将变为以下内容:
{
"name": "@example/components",
"dependencies": {
"react": "^16.14.0",
"react-dom": "^18.3.1"
}
}
使用 codemod
快速重构项目为 Catalogs
协议
pnpx codemod pnpm/catalog
{
"name": "@example/A",
"dependencies": {
"react": "^16.14.0",
"react-dom": "^18.3.1"
}
}
{
"name": "@example/B",
"dependencies": {
"react": "^18.3.1",
"react-dom": "^18.3.1"
}
}
执行完命令后:
catalog:
react-dom: ^18.3.1
{
"name": "@example/A",
"dependencies": {
"react": "^16.14.0",
"react-dom": "catalog:"
}
}
参考链接
- pnpm Catalogs
- Turbo - Best practices for dependency installation
- vue 是如何使用 catalogs 协议
- ViteConf 2023 | pnpm Catalogs — A New Tool to Manage Dependencies in monorepos
ViteConf 2024
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 kshao-blog-前端知识记录!
评论