这篇笔记📒主要记录: 在pnpm的monorepo工作区中,一个子包怎么把其他的子包作为依赖, 顺便延伸到monorepo的概念,pnpm的workspace实现monorepo.
- monorepo的概念
- React、 Vue、 Angular实现monorepo的实现方式(实现workspace的方式)
- 用pnpm的workspace实现monorepo (Vue.js实现monorepo的方式)
- 在pnpm的monorepo工作空间中,一个子包怎么把其他的子包作为依赖
monorepo的概念
先对齐下概念,monorepo, mono为前缀的时候表示单个,repo是repository(仓库)的简写,所以表示单个代码仓库的意思。就是把所有的项目代码都放在一个代码仓库里。
一个包里面有多个子包,每个子包都可以有自己的依赖,构建命令,package.json. 前端React、Vue、Angular都是monorepo这种形式。
React.js packages里面有多个子包
Vue.js packages里面有多个子包
Angular.js packages里面有多个子包
React、Vue、Angular实现monorepo的实现方式
React实现monorepo的实现方式
在2017年的时候,Dan Abramov就用了Yarn的workspaces实现monorepo.
{
"workspaces": [
"packages/*"
]
}
看下yarn的文档
Workspaces are the name of individual packages that are part of the same project and that Yarn will install and link together to simplify cross-references.
This pattern is often called monorepo when used in conjunction with a repository. Workspaces were initially popularized by projects like Lerna, but Yarn was the first package manager to provide native support for them - support which never stopped improving over years as we build more features around them.
大概翻译下就是: Workspaces(工作区)是同一项目中各个独立包的名称,Yarn 会安装并链接这些包,以简化它们之间的交叉引用。
这种模式在与代码库一起使用时通常称为 monorepo。Workspaces(工作区)最初由像 Lerna 这样的项目推广,但 Yarn 是第一个为它们提供原生支持的包管理器,而且随着我们围绕它们构建更多功能,这种支持在多年来不断改进。
Vue实现monorepo的实现方式
Vue是通过Pnpm的workspaces,看下工作区文档描述
pnpm has built-in support for monorepositories (AKA multi-package repositories, multi-project repositories, or monolithic repositories). You can create a workspace to unite multiple projects inside a single repository.
A workspace must have a
pnpm-workspace.yamlfile in its root. A workspace also may have an.npmrcin its root.
大概翻译下: pnpm 内置了对 monorepositories(即多包仓库、多项目仓库或单一仓库)的支持。你可以创建一个工作区来将多个项目统一在一个仓库中。
一个工作区必须在其根目录中包含一个 pnpm-workspace.yaml 文件。工作区的根目录中也可以包含一个 .npmrc 文件。
看下Vue的配置
packages:
- 'packages/*'
Angular实现monorepo的实现方式
应该是Google自己的工具Bazel, 如果有知道的,可以评论区回复下。
在pnpm的monorepo工作空间中,一个子包怎么把其他的子包作为依赖
回到写这篇笔记的最初,因为我用pnpm的workspace, 子包安装其它子包的时候,安装不成功, 项目结构是这样子的,
compact-vue/
├── packages/
│ ├── reactivity/
│ │ ├── package.json
│ │ └── src/
│ |
│ └── shared/
│ ├── package.json
│ └── src/
├── pnpm-workspace.yaml
├── package.json
└── .npmrc
执行的这个命令安装,
pnpm add @compact-vue/shared --filter reactivity
就是子包reactivity要依赖子包@compact-vue/shared,
提示This error happened while installing a direct dependency of /Users/gongzemin/Documents/playground/compact-vue/packages/reactivity
看下了pnpm workspace文档的用法, 有这么一句话
If link-workspace-packages is set to
true, pnpm will link packages from the workspace if the available packages match the declared ranges. For instance,foo@1.0.0is linked intobarifbarhas"foo": "^1.0.0"in its dependencies andfoo@1.0.0is in the workspace. However, ifbarhas"foo": "2.0.0"in dependencies andfoo@2.0.0is not in the workspace,foo@2.0.0will be installed from the registry. This behavior introduces some uncertainty.
翻译下: 如果 link-workspace-packages 设置为 true,pnpm 将会链接工作区中的包,如果可用的包符合声明的范围。例如,如果 bar 的依赖中有 "foo": "^1.0.0",且 foo@1.0.0 在工作区中,那么 foo@1.0.0 将被链接到 bar 中。然而,如果 bar 的依赖中有 "foo": "2.0.0",且 foo@2.0.0 不在工作区中,那么 foo@2.0.0 将从注册表中安装。这种行为会引入一些不确定性。
就是说我们要设置link-workspace-packages为true, 才可以把这些包link起来
增加.npmrc
link-workspace-packages=true
再次执行pnpm add @compact-vue/shared --filter reactivity, 就安装成功了
安装成功是这样子,通过workspace协议
Tip 一些命令
pnpm add -D vitest -w // -w表示把vitest安装到workspace,而不是workspace下面的包。
pnpm add packageName // 在子目录路径下可以安装想要的包名
pnpm add packageName --filter subpackage // 在外面主目录下给subpackge安装包