名词解释
- 多个项目的代码放在在同一存储库中这种开发策略称之为
Monorepo lernaBabel开发用来管理多包的工具,基于Monorepo理念在工具端的实现yarnFacebook 贡献的 Javascript 包管理器commitlint用来规范git commit信息
背景
在 vue-json-schema-form 项目中,需要把 lib、doc、demo 放在同一个项目中管理,彼此独立,又可以相互依赖。
使用 yarn workspace 可以很好的解决上面的问题,搭配 lerna 做npm发布管理。目前大型仓库都使用这种方式,比如 Vue Vuepress 等。
由于 yarn workspace 和 lerna 有较多的功能重叠,这里重叠的部分优先使用 workspace 。最后就是只有发布管理使用了 learn 其它使用 workspace
创建项目
目录结构
1 | ├── packages |
packages下每个文件夹为一个单独完整的包
package.json配置
1 | { |
子package配置
子package即为每个独立的工作区。
如:packages/demo,使用 vue-cli
1 | cd packages && vue create demo |
demo/package.json 配置:1
2
3
4
5
6
7{
"private": true, // 禁止发布
"publishConfig": {
"access": "publish" // 如果该模块需要发布,对于scope模块,需要设置为publish,否则需要权限验证
}
}
yarn workspace
yarn install
安装所有依赖,包含子package依赖,如果子package之间存在相互依赖会通过创建软链的方式引用,而非npm下载,这里可能会影响webpack配置中使用 node_modules 做路径判断的地方。
1 | yarn install |
依赖树关系
1 | yarn workspaces info |
安装/删除依赖模块
单个package工作区
1 | # packageA 安装 axios |
packageA是需要安装依赖的包名,即package.json中的name字段,而非目录名
root package1
2
3
4
5# root package 安装 commitizen
yarn add -W -D commitizen
# root package 移除 commitizen
yarn remove -W commitizen
运行单个 package 的scripts 命令
1 | # 运行packageA 的dev命令 |
1 | # 这里是在每个工作区运行 run build 命令 |
Tips:这里运行命令的时候不会检测依赖树关系,只是
package.json文件workspaces配置工作区逐个运行,这里推荐使用lerna build见下文 lerna build
到这里对于不需要推送npm的情况下已经可以满足基本需要了。
lerna
目前使用lerna主要来做发布和版本管理
- 全局安装
1 | npm i -g lerna |
- 初始化一个项目
1 | lerna init |
包含两种工作模式:
Fixed/Locked mode (default)
固定模式,默认packages下的所有包共用一个版本号(version),会自动将所有的包绑定到一个版本号上(该版本号也就是lerna.json中的version字段),所以任意一个包发生了更新,这个共用的版本号就会发生改变。Independent mode
独立模式,允许每一个包有一个独立的版本号,在使用lerna publish命令时,可以为每个包单独制定具体的操作,同时可以只更新某一个包的版本号。lerna.json中的version字段指定为independent即可,或者lerna init --independent命令初始化
lerna.json 文件配置大致如下1
2
3
4
5
6
7
8
9
10
11
12
13
14
15{
"npmClient": "yarn",
"useWorkspaces": true, // 使用yarn workspaces
"version": "0.0.1", // 当前版本 或者 independent 独立模式
"command": {
"version": {
"allowBranch": "master",
"exact": true,
"ignoreChanges": [
"**/*.md"
],
"message": "build: release version %v"
}
}
}
lerna clean
清除所用的 node_modules 目录1
lerna clean
lerna diff
显示修改内容 类似git diff1
lerna diff
lerna ls
列出所有的子package1
lerna ls -l
lerna changed
列出修改过的子package1
lerna changed
lerna build
build 所有子package,子package分别执行 build,--sort 参数可以控制以拓扑排序规则执行命令1
lerna run --stream --sort build
lerna version
lerna version 的作用是进行 version bump,支持手动和自动两种模式
手动确定新版本
1 | # 按着提示选择版本即可 |
自动确定版本
自动根据 conventional commit 规范确定版本
存在feat提交: 需要更新minor版本
存在fix提交: 需要更新patch版本
存在BREAKING CHANGE提交: 需要更新大版本
1 | # 生成changelog文件以及根据commit来进行版本变动 |
可参见官方文档 lerna version
version 成功后会自动推送当前分支,可以结合配置 lerna.json文件 command 下 version字段 配置允许version的分支,commit 信息等
1 | { |
lerna publish
lerna publish 的功能可以即包含version的工作,也可以单纯的只做发布操作。
可参见官方文档 lerna publish
1 | lerna publish |
lerna publish 会先调用 lerna version,再确定是否要发布到npm
1 | lerna publish from-git |
from-git 基于当前git提交的软件包做发布,一般都是通过 lerna version 提交的版本
1 | lerna publish from-package |
from-package 在注册表中不存在该版本的最新提交中发布程序包 (这个我没用过)
lerna不会发布标记为私有的软件包(package.json中"private": true)
changelog
根据 conventional commit 提交规范,即可通过工具为每个 package 生成 changelog 文件。
conventional commit 支持
conventional commit规范使用也可以看这个:Commit message 和 Change log 编写指南
安装如下依赖:1
yarn add -W -D commitizen cz-conventional-changelog @commitlint/cli @commitlint/config-conventional husky conventional-changelog-cli
commitizen:
一个撰写合格
Commit message的工具
cz-conventional-changelog:
用于使
commitizen支持Angular的Commit message格式
配置 package.json 添加如下配置1
2
3
4
5
6
7{
"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
}
}
}
至此就可以通过 git cz 命令替换 git commit 生成符合格式的Commit message。
git cz 命令出现如下选项

@commitlint/cli:
commitlint 用于检查您的提交消息是否符合提交格式,类似 eslint 校验js语法
@commitlint/config-conventional:
commitlint 校验规则,类似 eslint-config-standard
添加并配置 .commitlintrc.js 文件1
2
3
4
5
6module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
...otherRules // 可以继续配置你的规则
}
};
husky:husky是 Git hooks 工具,这里用于在 commit 时校验message内容
配置 package.json 文件,添加如下
1 | { |
至此当新提交的commit message 不符合规范便会阻止提交。
conventional-changelog-cli:
根据commit message生成 changelog.md 文件 (这里功能和 lerna version --conventional-commits 生成changelog 有部分重叠,下文会详细区分)。
如:conventional-changelog -p angular -i CHANGELOG.md -s -r 2
注意:这里生成的是整个仓库的
changelog,而非每个 package生成changelog
生成changelog
生成changelog 依赖如上 conventional-commit 规范message
整个仓库 changelog
生成自从上次发布以来的变动:1
conventional-changelog -p angular -i CHANGELOG.md -w
如果这是您第一次使用此工具,并且想要生成所有以前的变更日志,则可以执行:1
conventional-changelog -p angular -i CHANGELOG.md -s -r 0
每个package工作区独立 changelog
lerna version 时,自动模式 --conventional-commits 命令会同时为每个package工作区生成 changelog
1 | lerna version --conventional-commits |
注: lerna version 成功之后便会为每个 package 生成 changelog,包括 root package
npm scripts
如下:自己常配的一些script
1 | { |
changelog生成整个仓库changelogpublish手动选择版本并发包 (其实我自己平时一般用这个)autoPublish自动确定版本并发包同时生成每个package changelogversion自动确定版本不发布和生成每个package changelog