一、为什么需要多包管理

在大型前端项目中,我们经常会遇到这样的问题:一个仓库里有多个相互关联的包,比如组件库、工具库、业务模块等。如果每个包都单独管理依赖,不仅会导致重复安装,还会增加构建和发布的复杂度。这时候,yarn workspaces 就能派上用场了。

举个例子,假设我们有一个项目,包含三个包:

  • @project/components(UI组件库)
  • @project/utils(工具函数库)
  • @project/app(主应用)

如果这三个包分别放在不同的仓库,每次修改工具库后,都要手动更新依赖版本,非常麻烦。而 yarn workspaces 可以让它们共享同一个 node_modules,并且自动处理依赖关系。

二、如何配置 yarn workspaces

首先,确保你的项目根目录有一个 package.json,并添加 workspaces 字段:

{
  "name": "monorepo-project",
  "private": true,
  "workspaces": [
    "packages/*"
  ]
}

然后在根目录创建 packages 文件夹,里面存放各个子包:

monorepo-project/
├── package.json
├── packages/
│   ├── components/
│   │   └── package.json
│   ├── utils/
│   │   └── package.json
│   └── app/
│       └── package.json
└── yarn.lock

每个子包的 package.json 需要正确声明依赖关系。例如,@project/app 依赖 @project/components

{
  "name": "@project/app",
  "version": "1.0.0",
  "dependencies": {
    "@project/components": "1.0.0"
  }
}

运行 yarn install 后,所有依赖会被统一安装到根目录的 node_modules,并且子包之间的依赖会自动链接。

三、依赖共享与版本管理

yarn workspaces 最大的优势是依赖共享。比如,@project/components@project/utils 都依赖 lodash,那么 lodash 只会被安装一次,避免重复占用磁盘空间。

但要注意,如果不同子包依赖的 lodash 版本不同,yarn 会尽量兼容,但可能会引发冲突。这时候可以用 resolutions 字段强制统一版本:

{
  "resolutions": {
    "lodash": "4.17.21"
  }
}

四、批量构建与优化

在大型项目中,手动构建每个子包效率很低。我们可以利用 yarn workspace 命令批量执行脚本。例如,给所有子包添加 build 脚本:

// packages/components/package.json
{
  "scripts": {
    "build": "webpack --config webpack.config.js"
  }
}

然后在根目录的 package.json 中添加:

{
  "scripts": {
    "build": "yarn workspaces run build"
  }
}

运行 yarn build 时,所有子包的 build 脚本都会被执行。

五、应用场景与优缺点

适用场景:

  • 多包项目,尤其是组件库 + 工具库 + 应用的组合。
  • 需要频繁修改依赖关系的项目。
  • 希望减少 node_modules 体积的团队协作项目。

优点:

  • 依赖共享,减少磁盘占用。
  • 自动处理子包之间的依赖链接。
  • 支持批量执行脚本,提升开发效率。

缺点:

  • 如果子包依赖版本差异较大,可能导致冲突。
  • 调试时可能需要额外配置(如 source-map)。
  • 不适合小型项目,会增加复杂度。

六、注意事项

  1. 避免循环依赖:如果 A 依赖 BB 又依赖 A,会导致安装失败。
  2. 谨慎使用 resolutions:强制统一版本可能影响某些包的正常运行。
  3. 合理划分子包:不要过度拆分,否则会增加管理成本。

七、总结

yarn workspaces 是管理多包项目的利器,尤其适合大型前端项目。它能优化依赖管理、提升构建效率,但也需要合理规划子包结构。如果你正在维护一个复杂的代码库,不妨试试它!