共计 3022 个字符,预计需要花费 8 分钟才能阅读完成。
我前段时间参加了一个 react
为主的大前端我的项目,笼罩 Web、Android、Ios 三个平台。因为整个业务逻辑偏重在手机端,且 Web 端也是到了我的项目中期才开始启动,我在搭底层框架时就没有思考用相似 react-native-web
这样的框架把三端对立,而是别离以 react-native
和react
为主起了两个我的项目来应答。
因为无论哪一端,调用的后端微服务集群都是同一个,导致两个我的项目中还是不可避免的呈现了一些反复逻辑,我尝试了封装成 npm
包来重用逻辑,但仅限于哪些通用且变动较少工具类代码,对于变动频繁的业务逻辑代码,封装进去的 npm
包时不时就要更新版本,且抽出到我的项目之外也不易开发和调试,用起来分外麻烦,得失相当。
最近尝试了lerna
,惊喜的发现它岂但能解决过后我的项目的痛点,还能额定带来一些多项目管理相干的益处。
引入 lerna
lerna
的名字来源于希腊神话中的九头蛇海德拉(Lernaean Hydra),长相可参考我的项目 logo,拿它形容多我的项目工程是再贴切不过了。
lerna
的引入比设想中简略,其实,与其说引入 lerna
,倒不如说是导入到lerna
更适合,因为具体的做法是通过命令行创立了一个新的 lerna
我的项目,而后把所有我的项目导入进去。而且在导入的同时,每个我的项目的 git 提交记录也都合并在了一起。
lerna init
lerna import 你本地的我的项目门路
每个被导入的我的项目都会被寄存在根门路的 packages 目录下,上面是我 demo 我的项目的截图。
应用 lerna 来治理我的项目依赖
引入 lerna
后,第一件事就是要解决装置依赖的问题,咱们须要用 lerna add
命令来代替咱们习惯的npm
或yarn
,比如说当初给截图中的 rntest
我的项目装置 lodash
,就要执行上面的命令,该命令的底层实现也还是调用哦npm install
之类的命令。
lerna add lodash --scope=rntest
不过,执行后你会发现其余我的项目中 package-lock.json 都产生了变动,让人十分困惑,这背地的起因是跟增加依赖后主动执行的装置命令 lerna bootstrap
无关。
lerna 的依赖晋升
lerna
能够通过 lerna bootstrap
一行命令装置所有子项目的依赖包,而且在装置依赖时还有依赖晋升性能,所谓“依赖晋升”,就是把所有我的项目 npm 依赖文件都晋升到根目录下,这样能防止雷同依赖包在不同我的项目装置屡次。比方多个我的项目都用了 redux
,通过依赖晋升,只须要下载一次放到根目录的 node_modules 目录下,就可供其余所有我的项目来应用。不过,须要额定的参数--hoist
让依赖晋升失效。
lerna bootstrap --hoist
然而主动执行 lerna bootstrap
命令是不带依赖晋升参数的,这就导致下面每个我的项目的 lock 文件都会被批改的起因。
当然,要解决这个问题也容易,能够通过 lerna
的配置来防止 npm 对 lock 文件的批改即可,写法如下:
yarn 是 lerna 的最佳搭档
lerna
默认应用 npm
作为装置依赖包工具,但也能够抉择其余工具。yarn
在 1.0 版本之后提供了 workspaces 的性能,该性能从更底层的中央提供了依赖晋升,做的事件跟 lerna
一模一样。把它跟 lerna
放在一起看,几乎就像是为 lerna
量身定做一样。因而,举荐在 lerna 中搭配 yarn 一起应用。
把 npm 替换成 yarn 只需在 lerna 的配置文件增加两行代码即可,配置完当前立即顺畅百倍。
高效的代码重用
在我参加的这个大前端我的项目里,多端之间代码反复的局部蕴含 redux
中的业务逻辑、http 申请的解决、代码标准工具的查看、git
钩子中的自定义脚本等等。在 lerna
架构下,前两者可间接抽取到一个独立的我的项目,而后被其余我的项目援用,比方在我的 demo 中,能够像其余依赖包一样间接引入 shared
我的项目, lerna 会自动识别并把它导向外部我的项目。
import shared from 'shared'
这跟间接封装成 npm
包的一大区别就是实时更新,批改立即可见,就像在同一个我的项目一样,不影响开发和调试。
git 钩子和自定义脚本的重用
我尝试把解决 git
钩子的工具 husky
装置到了根目录,触发的事件和自定义脚本能笼罩到每个我的项目,给这部分代码重用带来了极大遍历。比方,不少我的项目会增加自定义脚本来束缚 git commit
提交时的音讯形容,在 lerna
架构下,只需写一次即可。
eslint 的重用
那些经常须要在根目录增加配置文件的第三方依赖,比方 eslint
、prettier
、babel
等,在 lerna
中无奈简略粗犷的晋升合并到一处。因而,对于 eslint
这种前端开发已不可或缺的工具,能够尝试将所有配置项抽取到独立我的项目,而后装置第三方依赖的形式引入,相似 eslint-config-airbnb
,eslint-config-prettier
,eslint-config-google
这样。
不得不说,即使不必 lerna
框架咱们也能够这么做,只不过在 lerna
框架下批改立即可见,不便了调试和开发。
lerna 框架下的 CI/CD
多我的项目的构造无疑给 CI/CD
带来挑战,好在支流的 CI 框架能完满解决这个问题。比方在 gitlab 上,only/changes
参数齐全满足了咱们的需要,让咱们能够为每一个子项目设置独自的 pipeline,比方当初咱们设置一个 pipeline,只当 rntest 我的项目下的文件被批改时才会触发:
在 lerna 框架下,所有我的项目都合在一个工程里,但 CI/CD
并不用这样。通过把脚本中的要害参数配置到 CI/CD
的我的项目内里,共用同一份 .gitlab-ci.yml
文件,从而可能实现每个子项目对应一个独立的 CI/CD
我的项目,最终 CI/CD
构造如下图:
lerna 框架下的子项目权限
因为所有的我的项目都归并到了一个 lerna
工程下,一旦有了拜访权限意味着你能够批改所有子项目中的代码,在理论的开发工作中多多少少会带来一些麻烦。比如说,开发 web 和开发 mobile 平台的是两个不同的团队,如果我作为 web 组的一员,一不小心批改了或删除了 mobile 我的项目的文件该怎么办?如果不退出任何限度,这种事件迟早会产生,我想这可能是 lerna
框架与生俱来的的痛点。
可怜的是,在 lerna
框架下,gitlab 或 github 这类第三方代码托管平台,自身的权限治理性能无奈解决这问题。但好在有其余工具的帮忙能够缓解这种痛,我尝试用来束缚开源贡献者提交 PR 标准的工具 dangerjs
来实现权限分隔,利用的信息就是以后 gitlab 账号的用户名,看起来成果还不错。
这个工具会在合并 MR 的时候,判断出我 gitlab 账号没有权限批改 rntest 子项目内的文件,因而禁止合并此 MR,并将这些信息主动增加到 MR 的评论里。当然,脚本判断的逻辑比拟简陋,仅用来做演示用,而对于 dangerjs
的局部我会另写一篇文章具体介绍。
结语
大前端我的项目将会是前端倒退的趋势,如何更好的治理大前端我的项目是每一位前端开发躲不开的课题。lerna
框架通过合而为一的理念提供了一种解决方案,通过取长补短,咱们能够施展出 lerna
的最大效用。如果你还没有用过,兴许,下一个我的项目就能够试试看。
相干材料
lerna 的 github 地址
文章中的 demo