前言
1、workspace:pnpm中使用workspace协议的目的是将拒绝解析除本地 workspace 包含的 package 之外的任何内容。也就是说如果引入的项目需要强制使用本地包,则可以使用workspace:协议 。
2、微前端和Monorepo的关系:Monorepo是一种单仓库多应用的代码管理方式。微前端是一种实现了多个子项目间样式隔离、JS隔离、路由、子项目通信等功能的项目架构模式。微前端使用Monorepo进行代码管理可以实现共享工程配置,同时又快捷地共享模块代码的功能。
3、pnpm:在使用monorepo方式管理项目时,会产生诸多问题,如幽灵依赖、依赖安装耗时的问题,需要使用pnpm进行解决这类问题。
所以,当仅仅需要对多个子项目间共享工程配置和模块间代码共享时使用Monorepo进行代码管理即可。
而当需要继承多个不同栈的模块或服务、每个模块需要独立开发部署、需要支持独立的生命周期和版本控制等时使用微前端。
在开发项目的过程中,我们需要在一个仓库中管理多个项目,每个项目有独立的依赖、脚手架,这种形式的项目结构我们称之为Monorepo,pnpm workspace就是管理这类项目的方案之一。
一、pnpm
pnpm代表performance npm(高性能的npmn),同npm和yarn,都属于javascript包管理安装工具,它较npm和yarn在性能上得到很大提升,被称为 快速地,节省磁盘空间的包管理工具。
二、对比lerna+yarn
使用lerna+yarn组合,也可以实现Monorepo项目管理。但是相比来说,更推荐pnpm workspace来管理。
三、构建一个Monorepo
先上最终的项目结构:
1 | Monorepo |
如上图,我们最终要创建如上图的一个项目结构,其中umi-antd是主项目,web文件夹下的都是子项目,供umi-antd调用。
1、创建主项目
主项目这里是使用的umi项目,这里也可以构建基于其他打包工具的各类项目,只要是遵守package.json配置条例的项目,都是可以的。
构建umi项目
1 | pnpm dlx create-umi@latest |
这里选择创建Ant Design Pro项目。
1 | $ npx create-umi@latest |
2、创建子项目common1
- 进入Monorepo>web目录,创建common1文件夹
- 然后进入common1目录,执行命令npm init对项目进行初始化,这时候会生产一个package.json文件
新建index.ts文件,代码如下:
1 | export default function print(msg:string) { |
3、创建子项目common2
步骤和创建common1一致
4、主项目中引入子项目
安装common1和common2。
1 | pnpm -F umi-antd add common1 |
安装完成后,在umi-antd依赖中出现两个子项目的软链接(或者叫符号链接)。
在业务代码中调用子项目输出的方法:
1 | //umi-antd\src\pages\Home\index.tsx |
5、运行主项目
到这里基本搭建完毕,这时候的整体项目结构如图:
然后执行命令启动主项目:pnpm -F umi-antd start,我们可以看到,控制台打印出来子模块中的信息。
6、子模块调用子模块
子模块也是可以相互调用的,这里我们在common1中引入common2的方法。
执行命令pnpm -F common1 add common2
在common1中调用common2中方法,代码如下:
1
2
3
4
5
6//web\common1\index.ts
import print2 from 'common2';
export default function print(msg:string) {
console.log(msg);
print2("这里是common1中调用common2");
}
再次运行umi-antd项目时,我们可以看到,控制台已经打印了common2中方法。
四、workspace协议(workspace:)
1、协议概述
默认情况下,如果可用的 packages 与已声明的可用范围相匹配,pnpm 将从工作区链接这些 packages。 例如, 如果bar引用”foo”: “^1.0.0”并且foo@1.0.0存在工作区,那么pnpm会从工作区将foo@1.0.0链接到bar。 但是,如果 bar 的依赖项中有 “foo”: “2.0.0”,而 foo@2.0.0 在工作空间中并不存在,则将从 npm registry 安装 foo@2.0.0 。 这种行为带来了一些不确定性。
幸运的是,pnpm 支持 workspace 协议 workspace: 。 当使用此协议时,pnpm 将拒绝解析除本地 workspace 包含的 package 之外的任何内容。 因此,如果您设置为 “foo”: “workspace:2.0.0” 时,安装将会失败,因为 “foo@2.0.0“ 不存在于此 workspace 中。
当 link-workspace-packages 选项被设置为 false 时,这个协议将特别有用。 在这种情况下,仅当使用 workspace: 协议声明依赖,pnpm 才会从此 workspace 链接所需的包。
以上是官网的解释,实际在使用的时候,如果引入的项目需要强制使用本地包,则可以使用workspace:协议。改造下umi-antd的package.json文件如下:
1 | "dependencies": { |
上面加上common1和common2的依赖声明后,会强制到本地寻找,找不到也不会到npm registry对应的私仓去下载。
2、版本符号
workspace协议,区分*、~、^、版本号,表示的意义各部相同,具体如下:
1 | { |
五、Monorepo工具有哪些?
Monorepo 是一种代码管理策略,它将一个项目的所有代码存储在一个单独的版本控制库中。Monorepo 解决了多个问题:解决了代码共享与重复的困扰,提供更好的可追踪性和一致性。通过使用Monorepo,开发团队可以更好地组织、共享和管理代码,提高开发效率和协作质量。选择合适的Monorepo工具并灵活运用,能够帮助开发者更好地应对复杂的软件开发需求,推动项目的成功完成。
参考: