封装Vue组件库(四)、Yarn workspaces 和 lerna
Yarn workspaces介绍workspaces 是工作区的意思。下面是一个简单的 monorepo 的组件库项目结构,每个组件都依赖了一些第三方模块:|- package.json|- packages||- button|||- package.json # 依赖lodash 4||- form|||- package.json # 依赖lodash 4||- formitem|||-
Yarn workspaces
介绍
workspaces 是工作区的意思。
下面是一个简单的 monorepo 的组件库项目结构,每个组件都依赖了一些第三方模块:
|- package.json
|- packages
| |- button
| | |- package.json # 依赖lodash 4
| |- form
| | |- package.json # 依赖lodash 4
| |- formitem
| | |- package.json # 依赖async-validator
| |- input
| | |- package.json # 依赖lodash 3
| |- steps
| | |- package.json
最外层的文件夹里是脚手架 package.json,因为所有的包都有相似的行为,所以这里面放所有包所需要的开发依赖,例如 babel storybook jest等。
packages中下存放所有包,每一个包对应一个组件,不同的包可能有不同的运行依赖(例如上例)。
每个包的 package.json 文件记录自己的依赖,常规情况下,需要给没有给每一个包安装各自的依赖。
button和form拥有相同的依赖(lodash 4),这时会出现重复下载,占用硬盘的情况。
开启 yarn workspaces 之后可以在根目录中使用 yarn install
给所有的包统一安装依赖。
如果不同的包中引用相同的第三方包,这个第三方包只会下载一次,并把相同的依赖,提升到根目录的 node_modules
中减少重复。
如果不同的包引用的依赖版本不同(例如示例中的 lodash 4 和 lodash 3),只会把相同版本的 lodash 提升到根目录的 node_modules
中,input中会单独下载 lodash 3。
npm 不支持 workspaces,所以之前安装依赖都要使用 yarn。
monorepo的项目结构,一般都会配合 yarn workspace 来管理包的依赖。
开启
使用 yarn workspaces 的项目,根目录被称为 workspace root
(工作区根目录)。
开启 yarn 的工作区只需要在项目根目录的 package.json 中添加这段代码:
"private": true,
"workspaces": [
"packages/*"
]
- private - 必须设置,作用是项目提交到 github 或 发布到 npm 的时候,禁止提交当前根目录的内容。
- 当组件库开发完毕后,要发布到 NPM。工作区的根目录一般是脚手架,不需要发布。private 是为了防止意外把内容暴露出去。
- workspaces - 一个数组,存储要管理的所有包的路径(也可以成为工作区 workspace),支持glob 通配符。
-
设置工作区中子目录(根工作区中的子工作区),当前设置的是 packages 目录下的任意包。
-
注意:由于使用通配符,如果这样使用
./packages/*
将会有问题,详细参考 Dots
-
使用
本文Yarn的版本是 v1.22.5。
使用 yarn workspaces 后无法直接 yarn add <pkg_name>
或 yarn remove <pkg_name>
,需要指定工作区。
- 安装根工作区(
workspace root
)的依赖- 安装所有工作区都可以使用的依赖,不会被添加到包(子工作区)的 package.json 中
- 例如:
yarn add jest -D -W
jest
- Facebook 的单元测试工具-D
- 作为开发依赖安装-W
---ignore-workspace-root-check
表示安装到工作区的根目录- 官方命令文档 或 使用
yarn help add
在命令行查看
- 给指定的工作区(包)安装单独的依赖
- 安装某个包的依赖,不需要切换到这个包的目录下,直接在根目录执行命令
- 例如:
yarn workspace button add lodash@4
button
- workspace_name 包名,package.json 中设置的 name,不是文件夹名
- 给所有工作区安装依赖
- 当项目从 git 仓库中下载后,直接执行
yarn [install]
就可以安装所有依赖 - 包括每个包各自的依赖,不需要依次去每个包的目录下执行安装命令。
- 如果多个包引入了相同的依赖,会走动把依赖的包提升到根目录的 node_modules 中,防止重复下载,节省硬盘空间,不需要存储在每个包的 node_modules 中。
yarn [install]
可以在项目根目录下执行,也可以在任何一个工作区目录下执行,效果一样。
- 当项目从 git 仓库中下载后,直接执行
- 删除依赖
- 工作区根目录:
yarn remove <pkg_name> -W
- 指定工作区:
yarn workspace <workspace_name> remove <pkg_name>
- pkg_name 依赖名,不加版本号
- 工作区根目录:
- 执行指定工作区的 scripts 命令
yarn workspace <workspace_name> run <script_name>
- 这样就不需要进入到工作区的目录才能执行它的脚本
这些命令建议在根目录执行。
yarn workspace 管理包的流程示例
以上面的目录结构为例:
执行 yarn workspace input add lodash@3
,当前项目中没有安装过 lodash@3,yarn默认会将其作为公共依赖提取,所以会优先在根目录下的 node_modules 安装 lodash 3.x.x。
然后执行 yarn workspace button add lodash@4
,由于已安装了不同版本的 lodash,并且当前只有 button 依赖 lodash@4,所以会在 button 工作区目录下的 node_modules 安装 lodash 4.x.x。
接着执行 yarn workspace form add lodash@4
,由于 lodash@4 被多个包依赖,并且 lodash@3 只被 input 依赖,所以会将 button 工作区安装的 lodash 4.x.x 提取到根目录的 node_modules 中,form 直接使用它。而原来的 lodash 3.x.x 被移动到依赖它的 input 目录下的 node_modules 中。
此时如果有一个新的包也安装 lodash@3,则根目录 node_modules 下的 lodash 又会替换为 lodash 3.x.x,依赖它的包中的 lodash 被提取,并且依赖 lodash@4 包的 node_modules 下重新包含 lodash 4.x.x。
当依赖数量发生变化,yarn 总会将依赖次数更多的那个版本提取到根目录 node_modules 下,而依赖其他版本的包则在自己目录下的 node_modules 中重复安装。
所以如果安装包的依赖时没有被提取到根目录,请查看根目录下是否已经安装了该依赖。
Lerna
介绍
假设组件库开发完毕,想要把所有组件提交到 Github 和 npm 上。
可以使用 Lerna,它可以统一发布项目中的所有包。
- Lerna 是 babel 维护自己的 monorepo,并开源出的一个项目。
- Lerna 是一种工具,用于优化使用git和npm管理多包存储库的工作流程。
- 用于管理具有多个包的 JavaScript 项目。
- 它可以一键把代码提交到 git 和 npm 仓库。
- Lerna 也可以管理包的依赖,它可以选择使用 npm 还是 yarn,需要单独配置。
- 如果使用 yarn,可以开启 yarn workspaces。
- 一般会把 Leran 和 yarn workspaces 结合使用。
- 使用 Lerna 发布,使用 yarn workspaces 管理包的依赖。
使用
-
全局安装
yarn global add lerna
-
初始化
lerna init
初始化完毕会做几件事情:
-
如果当前项目没有被 git 管理,会进行 git 初始化
-
在项目根目录创建一个 lerna.json 的配置文件
// lerna.json { // 所要管理的包的路径,默认是["packages/*"],不是从 package.json 获取的 // 如果根目录中没有 packages,就会自动创建该目录 "packages": [ "packages/*" ], // 当前项目初始化版本 "version": "0.0.0" }
- 在 package.json 中添加开发依赖(保证其他开发者使用时安装了lerna)
{ //... "devDependencies": { //... "lerna": "^3.22.1", } }
-
-
发布项目
lerna publish
- 首先要在 Github 上创建一个远程仓库
- 还需要登录到 npm,发布npm还要保证是 npmjs 的镜像源
- 然后再运行
lerna publish
,可以同时把项目提交到 Github,并把所有的包发布到 npm
# 检查npm是否登录 npm whoami # 登录npm npm login # 查看npm镜像源是否是npmjs: https://registry.npmjs.org npm config get registry
# 发布 lerna publish # 选择提交的版本,根据需要选择 ? Select a new version (currently 0.0.0) (Use arrow keys) # Patch(0.0.1) # 是否要提交这些包,把这些包从0.0.0的版本提升为0.0.1 ? Are you sure you want to publish these packages? (ynH) # Y # 接着就会提交到github并发布到npm,如果npm上有同名的包就会发布失败。
发布后,每个包下的 package.json 中的 version 被修改为新的版本号 0.0.1
lerna 会以新的 version 创建 tag(例如当前就是 v0.0.1),并将这些改动提交到 git 和 npm。
注意:
- 如果包的内容没有改动,lerna会提示
lerna success No changed packages to publish
,不会发布。 - 包改动了,还需要提交
commit
,否则lerna识别不到它的更新,也不会发布。
learn publish 发布时还会在包的 package.json 中添加 gitHead 字段,存储一个 SHA。
但是我在执行命令的时候,虽然中途添加了这个字段,但最终又被移除了,目前不知道为什么。
庆幸的是,似乎没有影响到什么。
lerna publish
可以根据需要发布全部或部分包,具体参考官方文档 @lerna/publish
更多推荐
所有评论(0)