lerna
http://www.febeacon.com/lerna-docs-zh-cn/
Lerna + Yarn Workspace
- lerna 发布管理
- Yarn Workspace 依赖管理
总体版本采用 lerna publish 进行总体发布,此时会强行将各个 npm 包版本保持到和 lerna 发布的版本同步(因此 lerna 是进行统一 npm 包版本管理)。
npm install -g lerna
进入文件夹
lerna init
lerna init
初始化,加上--independent
参数,lerna 将会以独立版本控制的模式进行管理,即每个包将会是独立的版本号。
├── lerna.json
├── package.json
└── packages
├── pkg1
│ ├── index.js
│ └── package.json
└── pkg2
├── index.js
└── package.json
lerna add
将本地或远程package作为依赖项添加到当前 Lerna 存储库中的包。一般用来软连接
#将 module-1 包添加到 'prefix-' 前缀文件夹中的包中
lerna add module-1 packages/prefix- *
#将模块 1 安装到模块 2
lerna add module-1 --scope=module-2
#在 devDependencies 中安装 module-1 到 module-2
lerna add module-1 --scope=module-2 --dev
#在 peerDependencies 中安装 module-1 到 module-2
lerna add module-1 --scope=module-2 --peer
#在除module-1之外的所有模块中安装module-1
lerna add module-1
#在所有模块中安装 babel-core
lerna add babel-core
lerna bootstrap
这个命令主要是用来执行 packages/ 目录下每个包的 npm install 命令,并将这些包直接的相互依赖关系进行链接。
lerna publish
通过 lerna publish 发布所有 npm 包的统一版本号,使所有 npm 包统一提升 MINOR 版本或 MAJOR 版本,通过 lerna 发布版本的同时会对项目整体进行打 tag。
lerna publish # 用于发布更新
lerna publish --skip-git # 不会创建git commit或tag
lerna publish --skip-npm # 不会把包publish到npm上
{
// 定义各个项目存放的位置,这里我们新增一个examples/
"packages": ["packages/*"],
// lerna 总体版本
"version": "0.0.0",
// 执行命令的client,默认为npm,这里我们需要配置为yarn
"npmClient": "yarn",
// 使用workspace,需要配置package.json
"useWorkspaces": true
}
开启yarn工作区
{
"name": "root",
"private": true,
"devDependencies": {
"lerna": "^4.0.0"
},
"workspaces": [
"packages/*" // 开启yarn工作区
]
}
yarn add jest -W // 根目录安装 全局安装
yarn workspace test1 add vue // 子项目安装
MAJOR.MINOR.PATCH(主版本号.次版本号.修订号):
无论是 yarn 还是 lerna 都可以总结为
- 将所有 package 的依赖都以扁平化的方式安装在工作区的根目录 node_modules,同时对于同一个依赖的不同版本,将其中一个版本安装到根目录,其他版本安装在各自 package 下的node_modules,解决依赖不同版本的冲突问题
- 通过将各个 package 都软链到根目录 node_modules,各个 package 利用 node 的递归查找机制,可以导入其他 package,不需要手动 link
- 通过将各个 package 中的 node_modules 的 bin 文件夹软链到根目录中的 node_modules,保证每个package 的 npm script 能正常运行
虽然解决了核心问题,但是又引入其他问题
- 幻影依赖(phatom)被放大,例如全部依赖声明都扁平化在根目录 node_modules,由于 node 的递归查找,你可以访问到任何其他 package 的依赖,以及依赖的依赖。
- 分身(doppelgangers)更容易出现,大量依赖的依赖不同版本,随机出现在 node_modules 的第一层,或者依赖的依赖中。
pnpm
pnpm介绍
- npm 1/2的问题:依赖是递归安装的,会导致文件路径过深,依赖重复下载的问题,导致node_modules体积过大。
- npm 3/yarn的问题:扁平化安装:
- 幽灵依赖问题:引用了依赖模块的依赖,但是未来可能被删除
- 分身依赖问题 :扁平化安装过程中,相同依赖的不同版本会同时存在各依赖模块中
- 非单例
- 体积大
monorepo问题:幽灵依赖和分身依赖问题会被放大
软链接 sybbolic link 和 硬链接 hard link
硬链接:inode 都指向同一个文件在硬盘中的区块,只能为文件创立 软链接:类似于windows系统中的快捷方式,与硬链接不同,软链接就是一个普通文件,只是数据块内容有点特殊,文件用户数据块中存放的内容是另一文件的路径名的指向,通过这个方式可以快速定位到软连接所指向的源文件实体。软链接可对文件或目录创建。
pnpm使用
- 安装 pnpm
npm i pnpm -g
然后pnpm init
项目
在根目录新建 pnpm-workspace.yaml,内容如下:
packages:
# all packages in subdirs of packages/ and components/
- 'packages/**
我们所有的子项目都放在 packages 目录下。
- 用 pnpm 安装全局共用的包,比如 lodash。注意这里使用
-w
表示把包安装在 root 下,
该包会放置在
pnpm install lodash -w // add也可以
pnpm remove 包
pnpm up //更新所有依赖项
pnpm upgrade 包 //更新包
如需要把依赖安装在所有 packages 下的各个包中,使用
-r
。使用
--filter
后面接子 package 的 namepnpm i vue@2 --filter pkg1
项目内互相依赖
pnpm i pkg2 -r --filter pkg1
"dependencies": {
"dayjs": "^1.11.1",
"pkg2": "workspace:^1.0.0", // 用workspace: *,就可以保持依赖的最新版本
"vue": "2"
}
├── packages
│ ├── pkg1
│ │ ├── package.json
│ │ └── pnpm-lock.yaml
│ ├── pkg2
│ ├── package.json
│ └── pnpm-lock.yaml
├── package.json
├── pnpm-lock.yaml
└── pnpm-workspace.yaml
参考资料
https://cloud.tencent.com/developer/article/1913720
https://zhuanlan.zhihu.com/p/419399115