Monorepo 依赖管理策略:深入理解 workspace 协议与依赖提升

约 10 分钟阅读

前言

依赖管理是 Monorepo 架构中的核心问题之一。如何正确配置依赖关系,避免重复安装,确保类型安全,是每个 Monorepo 项目必须解决的问题。

本文以 Vue Ace Admin 项目为例,深入解析 Monorepo 中的依赖管理策略。

如果你还不熟悉 Monorepo 基础配置,建议先阅读 从零搭建 Monorepo 项目

workspace 协议详解

什么是 workspace 协议

workspace:* 是 pnpm 提供的特殊协议,用于引用本地 workspace 中的包。

基本用法:

json
{
  "dependencies": {
    "@codexlin/ace-admin-hooks": "workspace:*",
    "@codexlin/ace-admin-ui": "workspace:*"
  }
}

workspace 协议的工作原理

本地开发时:

bash
# pnpm 自动创建符号链接
node_modules/@codexlin/ace-admin-hooks -> packages/hooks
node_modules/@codexlin/ace-admin-ui -> packages/ui

发布到 npm 时:

bash
# pnpm 自动替换为实际版本号
"@codexlin/ace-admin-hooks": "workspace:*" 
# 发布后变为
"@codexlin/ace-admin-hooks": "^1.0.0"

workspace 协议的优势

  1. 开发效率

    • 直接使用源码,修改立即生效
    • 无需构建即可使用
    • 完整的 TypeScript 类型支持
  2. 无缝切换

    • 本地开发和 npm 使用方式完全一致
    • 无需修改代码即可切换
  3. 版本同步

    • 自动使用最新版本
    • 避免版本不一致问题

依赖类型详解

dependencies - 运行时依赖

使用场景: 包运行时需要的依赖

示例:

json
// packages/ui/package.json
{
  "dependencies": {
    "ant-design-vue": "~4.2.6"
  }
}

特点:

  • 会被安装到 node_modules
  • 会被打包到最终产物中(除非 external)
  • 版本会被锁定

devDependencies - 开发依赖

使用场景: 只在开发时需要的依赖

示例:

json
// packages/ui/package.json
{
  "devDependencies": {
    "vite": "^6.0.0",
    "typescript": "~5.9.0",
    "vue": "^3.5.0"
  }
}

特点:

  • 只在开发时安装
  • 不会被打包到最终产物
  • 不会传递给使用该包的项目

peerDependencies - 对等依赖

使用场景: 期望宿主环境提供的依赖

示例:

json
// packages/ui/package.json
{
  "peerDependencies": {
    "vue": ">=3.4.0",
    "ant-design-vue": ">=4.0.0"
  }
}

特点:

  • 不会自动安装
  • 需要宿主环境提供
  • 避免重复安装,减小包体积
  • 版本要求更灵活

为什么使用 peerDependencies?

typescript
// 场景:UI 包依赖 Vue
// ❌ 不使用 peerDependencies
// 每个使用 UI 包的项目都会安装 Vue
// 导致多个 Vue 实例,体积增大

// ✅ 使用 peerDependencies
// Vue 由主应用提供,所有包共享同一个 Vue 实例
// 减小包体积,避免版本冲突

optionalDependencies - 可选依赖

使用场景: 依赖不存在时不影响功能

示例:

json
{
  "optionalDependencies": {
    "some-optional-package": "^1.0.0"
  }
}

依赖提升机制

pnpm 的依赖提升策略

pnpm 使用符号链接和硬链接来管理依赖,避免重复安装:

text
node_modules/
├── .pnpm/
│   ├── vue@3.5.13/
│   │   └── node_modules/
│   │       └── vue
│   └── ant-design-vue@4.2.6/
│       └── node_modules/
│           └── ant-design-vue
│
├── vue -> .pnpm/vue@3.5.13/node_modules/vue
└── ant-design-vue -> .pnpm/ant-design-vue@4.2.6/node_modules/ant-design-vue

优势:

  • 节省磁盘空间
  • 安装速度快
  • 版本管理清晰

依赖提升配置

根目录 .npmrc:

text
# 提升所有依赖到根目录
shamefully-hoist=true

# 提升 peerDependencies
public-hoist-pattern[]=*eslint*
public-hoist-pattern[]=*prettier*

使用场景:

  • 某些工具需要依赖在根目录(如 ESLint、Prettier)
  • 避免每个包都安装相同的开发工具

版本管理策略

版本号规范

语义化版本(SemVer):

  • major.minor.patch
  • major:不兼容的 API 变更
  • minor:向后兼容的功能新增
  • patch:向后兼容的问题修复

示例:

json
{
  "version": "1.0.0"  // hooks 包
  "version": "0.3.0"  // ui 包(仍在开发中)
}

版本同步策略

策略一:独立版本(推荐)

每个包独立管理版本:

json
// packages/hooks/package.json
{ "version": "1.0.0" }

// packages/ui/package.json
{ "version": "0.3.0" }

优势:

  • 版本管理灵活
  • 减少不必要的版本更新
  • 用户可以选择性安装

策略二:统一版本

所有包使用相同版本:

json
// 使用脚本同步版本
{
  "scripts": {
    "version:sync": "node scripts/sync-version.js"
  }
}

使用场景:

  • 包之间紧密耦合
  • 需要保持版本一致

实际案例:Vue Ace Admin 依赖配置

Hooks 包配置

json
// packages/hooks/package.json
{
  "name": "@codexlin/ace-admin-hooks",
  "peerDependencies": {
    "vue": "^3.0.0"  // Vue 由宿主环境提供
  },
  "devDependencies": {
    "vue": "^3.5.0",        // 开发时使用
    "typescript": "^5.0.0", // 类型检查
    "vite": "^6.0.0"        // 构建工具
  }
}

设计思路:

  • peerDependencies:Vue 由使用方提供
  • devDependencies:开发工具不传递给使用者

UI 包配置

json
// packages/ui/package.json
{
  "name": "@codexlin/ace-admin-ui",
  "peerDependencies": {
    "vue": ">=3.4.0",
    "ant-design-vue": ">=4.0.0"
  },
  "devDependencies": {
    "vue": "^3.5.0",
    "ant-design-vue": "~4.2.6",
    "typescript": "~5.9.0",
    "vite": "^6.0.0"
  }
}

设计思路:

  • peerDependencies:Vue 和 Ant Design Vue 由宿主提供
  • devDependencies:开发时使用完整版本进行测试

主应用配置

json
// package.json(根目录)
{
  "dependencies": {
    "@codexlin/ace-admin-hooks": "workspace:*",
    "@codexlin/ace-admin-ui": "workspace:*",
    "vue": "~3.5.13",
    "ant-design-vue": "~4.2.6"
  }
}

依赖关系图:

text
主应用
├── vue@3.5.13 (实际安装)
├── ant-design-vue@4.2.6 (实际安装)
├── @codexlin/ace-admin-hooks (workspace,使用主应用的 vue)
└── @codexlin/ace-admin-ui (workspace,使用主应用的 vue 和 ant-design-vue)

依赖管理最佳实践

1. 合理使用 peerDependencies

何时使用:

  • 框架类依赖(Vue、React)
  • UI 库依赖(Ant Design Vue、Element Plus)
  • 大型依赖(避免重复安装)

示例:

json
{
  "peerDependencies": {
    "vue": ">=3.4.0"  // ✅ 框架依赖
  },
  "dependencies": {
    "lodash-es": "^4.17.21"  // ✅ 工具库,可以打包
  }
}

2. workspace 包之间的依赖

Hooks 包 → UI 包:

json
// packages/ui/package.json
{
  "dependencies": {
    "@codexlin/ace-admin-hooks": "workspace:*"
  }
}

主应用 → 两个包:

json
// package.json
{
  "dependencies": {
    "@codexlin/ace-admin-hooks": "workspace:*",
    "@codexlin/ace-admin-ui": "workspace:*"
  }
}

3. 版本范围策略

开发依赖: 使用精确版本或小范围

json
{
  "devDependencies": {
    "typescript": "~5.9.0",  // 允许补丁版本更新
    "vite": "^6.0.0"         // 允许小版本更新
  }
}

运行时依赖: 根据兼容性选择

json
{
  "dependencies": {
    "vue": "~3.5.13",           // 锁定小版本
    "ant-design-vue": "~4.2.6"  // 锁定小版本
  }
}

4. 依赖更新策略

定期更新:

bash
# 检查过时的依赖
pnpm outdated

# 更新依赖
pnpm update

# 更新特定包
pnpm update vue@latest

安全更新:

bash
# 使用 pnpm audit 检查安全漏洞
pnpm audit

# 自动修复
pnpm audit --fix

常见问题与解决方案

Q1: peerDependencies 警告

问题: 安装时出现 peerDependencies 警告

text
WARN Issues with peer dependencies found
└─ ant-design-vue@4.2.6
  └─ ✕ missing peer vue@"^3.4.0"

解决方案:

bash
# 安装缺失的 peer 依赖
pnpm add vue@^3.4.0

# 或使用 --shamefully-hoist(不推荐)
pnpm install --shamefully-hoist

Q2: 版本冲突

问题: 不同包需要不同版本的依赖

解决方案:

  1. 使用 peerDependencies:让宿主环境决定版本
  2. 版本范围:使用兼容的版本范围
  3. 依赖提升:pnpm 自动处理版本冲突

Q3: workspace 包无法解析

问题: TypeScript 无法解析 workspace 包

解决方案:

json
// tsconfig.json
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@codexlin/ace-admin-hooks": ["./packages/hooks/src"],
      "@codexlin/ace-admin-ui": ["./packages/ui/src"]
    }
  }
}

总结

Monorepo 的依赖管理需要平衡多个因素:

  1. workspace 协议:实现本地开发和 npm 发布的无缝切换
  2. peerDependencies:避免重复安装,减小包体积
  3. 依赖提升:pnpm 的符号链接机制优化安装效率
  4. 版本管理:合理的版本策略确保兼容性

通过合理的依赖配置,可以实现:

  • ✅ 更小的包体积
  • ✅ 更快的安装速度
  • ✅ 更好的类型安全
  • ✅ 更灵活的版本管理

下一步,你可以学习:

如果你对 Vue 3 企业级工程实践 感兴趣,可以查看我们的 架构实践分类 下的其他文章。

相关文章