Open hardfist opened 5 years ago
从知乎过来看,结果图破了...又回去了 = =;
一个小错误提示:
安装|删除依赖 普通项目: 通过yarn add和yarn remove即可简单姐解决依赖库的安装和删除问题
多写了一个"姐"字
菜鸡借道请教一个问题=。= 如下: 我现在用lerna做一套组件开发,其中有一个private:true的package专门用来做组件展示,这个package依赖着其他的组件package并且使用了webpack 的HMR,想问一下有没有什么办法可以在改动其他组件package代码的时候也能触发热更新,以使改动很快的反馈在页面上。
菜鸡借道请教一个问题=。= 如下: 我现在用lerna做一套组件开发,其中有一个private:true的package专门用来做组件展示,这个package依赖着其他的组件package并且使用了webpack 的HMR,想问一下有没有什么办法可以在改动其他组件package代码的时候也能触发热更新,以使改动很快的反馈在页面上。
可能需要自己写些工具,开发模式下,link 某个需要更改的组件,修改组件,查看预览展示。然后提交组件的修改,unlink结束。想要完全靠 lerna 等现有库很难满足自己的需求。
很好的介绍, 希望有更多 lerna 结合 gitlab-ci 或 github-action 的场景介绍
菜鸡借道请教一个问题=。= 如下: 我现在用lerna做一套组件开发,其中有一个private:true的package专门用来做组件展示,这个package依赖着其他的组件package并且使用了webpack 的HMR,想问一下有没有什么办法可以在改动其他组件package代码的时候也能触发热更新,以使改动很快的反馈在页面上。
可以使用源码依赖的方式
基于lerna和yarn workspace的monorepo工作流
monorepo管理代码有众多好处,但是也带来了很多的技术上的挑战,github上的很多的项目都是使用lerna管理monorepo项目,我们探讨下在gitlab上也通过lerna和yarn workspace结合来管理项目。
由于yarn和lerna在功能上有较多的重叠,我们采用yarn官方推荐的做法,用yarn来处理依赖问题,用lerna来处理发布问题。能用yarn做的就用yarn做吧
一个非monorepo的普通项目,常见的开发流程如下,对于monorepo项目却可能存在各个问题
搭建环境
主要指安装依赖
普通项目:clone下来后通过yarn install,即可搭建完项目,有时需要配合postinstall hooks,来进行自动编译,或者其他设置。
monorepo: 各个库之间存在依赖,如A依赖于B,因此我们通常需要将B link到A的node_module里,一旦仓库很多的话,手动的管理这些link操作负担很大,因此需要自动化的link操作,按照拓扑排序将各个依赖进行link
解决方式:
通过使用workspace,yarn install会自动的帮忙解决安装和link问题(https://github.com/lerna/lerna/issues/1308)
清理环境
在依赖乱掉或者工程混乱的情况下,清理依赖
普通项目: 直接删除node_modules以及编译后的产物。
monorepo: 不仅需要删除root的node_modules的编译产物还需要删除各个package里的node_modules以及编译产物
解决方式:使用lerna clean来删除所有的node_modules,使用yarn workspaces run clean来执行所有package的清理工作
安装|删除依赖
普通项目: 通过yarn add和yarn remove即可简单姐解决依赖库的安装和删除问题
monorepo: 一般分为三种场景
给某个package安装依赖:yarn workspace packageB add packageA 将packageA作为packageB的依赖进行安装
给所有的package安装依赖: 使用yarn workspaces add lodash 给所有的package安装依赖
给root 安装依赖:一般的公用的开发工具都是安装在root里,如typescript,我们使用yarn add -W -D typescript来给root安装依赖
对应的三种场景删除依赖如下
项目构建
普通项目:建立一个build的npm script,使用yarn build即可完成项目构建
monorepo:区别于普通项目之处在于各个package之间存在相互依赖,如packageB只有在packageA构建完之后才能进行构建,否则就会出错,这实际上要求我们以一种拓扑排序的规则进行构建。
我们可以自己构建拓扑排序规则,很不幸的是yarn的workspace暂时并未支持按照拓扑排序规则执行命令,虽然该 rfc已经被accepted,但是尚未实现
幸运的是lerna支持按照拓扑排序规则执行命令, --sort参数可以控制以拓扑排序规则执行命令
项目测试
普通项目: 建立一个test的npm script即可
monorepo项目:有两种方式
使用统一的jest测试配置这样方便全局的跑jest即可,好处是可以方便统计所有代码的测试覆盖率,坏处是如果package比较异构(如小程序,前端,node 服务端等),统一的测试配置不太好编写
每个package单独支持test命令,使用yarn workspace run test,坏处是不好统一收集所有代码的测试覆盖率
版本升级及发包
项目测试完成后,就涉及到版本发布,版本发布一般涉及到如下一些步骤
条件验证
如验证测试是否通过,是否存在未提交的代码,是否在主分支上进行版本发布操作,以及其他条件
version_bump
发版的时候需要更新版本号,这时候如何更新版本号就是个问题,一般大家都会遵循 semVer语义,如果版本之间的提交记录较少,能够较为容易的手动更新版本好,但这样也存在人为失误的可能,更好的办法是根据git的提交记录自动更新版本号,实际上只要我们的git commit message符合 Conventional commit规范,即可通过工具根据git提交记录,更新版本号,简单的规则如下
存在feat提交: 需要更新minor版本
存在fix提交: 需要更新major版本
存在BREAKING CHANGE提交: 需要更新大版本
生成changelog
为了方便查看每个package每个版本解决了哪些功能,我们需要给每个package都生成一份changelog方便用户查看各个版本的功能变化。同理只要我们的commit记录符合 conventional commit规范,即可通过工具为每个package生成changelog文件
生成git tag:
为了方便后续回滚问题及问题排查通常需要给每个版本创建一个git tag
git 发布版本:
每次发版我们都需要单独生成一个commit记录来标记milestone
发布npm包:
发布完git后我们还需要将更新的版本发布到npm上,以便外部用户使用
我们发现手动的执行这些操作是很麻烦的且及其容易出错,幸运的是lerna可以帮助我们解决这些问题
lerna提供了publish和version来支持版本的升级和发布
publish的功能可以即包含version的工作,也可以单纯的只做发布操作。
lerna version
lerna version的作用是进行version bump,支持手动和自动两种模式
只发布某个package
不支持,lerna官方不支持仅发布某个package,见 https://github.com/lerna/lerna/issues/1691,如果需要,只能自己手动的进入package进行发布,这样lerna自带的各种功能就需要手动完成且可能和lerna的功能相互冲突
由于lerna会自动的监测git提交记录里是否包含指定package的文件修改记录,来确定版本更新,这要求设置好合理的ignore规则(否则会造成频繁的,无意义的某个版本更新),好处是其可以自动的帮助package之间更新版本
例如如果ui-form依赖了ui-button,如果ui-button发生了版本变动,会自动的将ui-form的对ui-button版本依赖更新为ui-button的最新版本。 如果ui-form发生了版本变动,对ui-button并不会造成影响。
自动选择发布版本
使用--conventional-commits 参数会自动的根据conventional commit规范和git commit message记录帮忙确定更新的版本号。
自动确立了如下版本更新
手动选择发布版本
如果git commit message发现不太靠谱,且无法修改的话,那么需要手动的确认新版本,version默认是手动选择版本
changelog.md
version完成后会自动生成changelog.md,但是由于lerna是根据什么规则来生成changelog的规则尚不清楚,现在发现A库的changlog里可能包含B的commit记录,具体原因待查
lerna publish
git vesion_bump完成后,就可以根据version生成的tag进行npm发包了
示例
完整的demo地址 https://github.com/hardfist/monorepo-starter
我们通过一个简单的项目来演示上述操作
创建项目
新建项目&&安装lerna&& 初始化lerna
lerna配置使用yarn workspaces, 使用independent模式(根据需求选择是否使用independent)
配置package.json使用yarn workspacess
创建package
创建ui-lib 模块
初始化ui-button模块
配置
创建ui-app 模块
同上,或者使用lerna create快速创建package
将ui-lib作为ui-app的依赖
将lodash添加为所有package的依赖(不包含root)
将typescript设置为root的开发依赖
一般root只包含一些开发工具依赖如webpack,babel,typescript等
构建和测试
为ui-lib和ui-app添加build和test和clean脚本
在root里添加build、test和clean脚本
添加conventional-commit支持
lerna的version_bump和changelog生成都依赖于conventional-commit,因此需要保证commit-msg符合规范。
添加@commitlint/cli和@commitlint/config-conventional以及husky
配置commitlint
配置commit-msg的hooks
发版
开发测试通过后,每隔一段时间即可发版,我们使用lerna version来做发版
配置发版的message
``
配置发版的策略,我们积极convention-commit来发版
发版
这个会提示用户输入版本,如果不想这个提示可以关闭
``
发包
发版成功后既可以发包,使用lerna publish即可发包
常见问题
见 https://github.com/lerna/lerna/issues/1425 原因是conventional-changelog造成的,讨论见 https://github.com/conventional-changelog/standard-version/issues/163 这可能造成很多的patch version,如果在乎这个可以使用canary release