感谢支持ayqy我的订阅号,每周义务推送1篇(only unique one)原创精品博文,话题包括但不限于前端、Node、Android、数学(WebGL)、语文(课外书读后感)、英语(文档翻译)
若是以为弱水三千,一瓢太少,能够去 http://blog.ayqy.net 看个痛快 前端
一.定位
Lerna is a tool that optimizes the workflow around managing multi-package repositories with git and npm.node
多模块管理工具,用来帮助维护monoreporeact
P.S.Lerna是Babel本身日用并开源的工具,见Why is Babel a monorepo?git
二.monorepo
monorepo(monolithic repository),与multirepo相对,分别是单代码仓库与多代码仓库(one-repository-per-module)github
multirepo即传统作法,按模块分为多个代码库,实践中发现一些问题:npm
issue管理混乱,常常有在core repo提module问题的,须要Close this and track thatjson
changelog难以整合,须要人工梳理全部变更的仓库,并作整合bootstrap
core repo版本更新麻烦,须要同步全部module更新其依赖的core repo版本bash
monorepo把全部相关module都放到一个repo里,每一个module独立发布,但使用与该repo统一的版本号(例如Babel和React),issue和PR都集中到该repo,changelog能够简单地从一份commit列表梳理出来(甚至若是按照commit规范关联issue tag的话,可以自动生成规范的changelog)微信
monorepo也存在一些问题,但不如上面提到的痛点强烈:
repo体积较大,可能带来版本控制的问题(Git不适合管理体积太大的repo)
统一构建工具,对构建工具提出了更高要求,要能构建各类相关module
从源码管理的角度来看,multirepo与monorepo是两种不一样的理念,前者容许多元化发展,各个module能够有本身的玩法(构建,依赖管理,单元测试等),后者但愿集中管理,减小玩法差别带来的沟通成本
monorepo标志性的特征是目录结构,例如React:
react-16.2.0/ packages/ react/ react-art/ react-.../
每一个module都有本身的依赖项(package.json
),可以做为独立的npm package发布,只是源码放在一块儿维护
典型案例:
rollup:multirepo
babel:monorepo
P.S.以前使用rollup遇到问题都先去主repo查相关issue,再根据线索找到对应的plugin repo,再查相关issue。一直感受异常麻烦,又说不出来哪里不对,原来是源码组织方式带来的困扰
三.lerna试玩
// 安装 npm install lerna -g git init hoho-lerna && cd hoho-lerna // 初始化目录结构 lerna init
获得以下结构:
hoho-lerna/ packages/ lerna.json package.json
建立module:
mkdir packages/hoho-lerna-core && cd packages/hoho-lerna-core npm init
这样最终会获得一堆package:
packages/ hoho-lerna-core/ package.json hoho-lerna-module-a/ package.json hoho-lerna-module-b/ package.json module.../
咱们实际作的事情是按模块拆分红package,并(经过module级的package.json
)声明了各package之间的依赖关系
依赖处理
若是moduleA依赖core,经过lerna bootstrap
命令处理依赖事后,会在moduleA
的node_modules
下建立软连接指向core
目录,有一只活生生的例子
注意:npm不会自动安装peerDependencies,lerna也不提供这个服务
lerna bootstrap
按照以前声明的依赖关系,经过创建软连接来把各package实际关联起来
发布package
既然都放在packages
里了,容易统一管理,因此支持一键发布全部package到npm
P.S.先要有npm帐号(自行注册),并npm adduser
添加到本地配置里
准备好以后,火烧眉毛的开始一箭n星:
lerna publish
不出意外的话,会获得相似输出:
lerna info version 2.7.0 lerna info current version 0.0.0 lerna info Checking for updated packages... lerna info Comparing with initial commit. lerna info Checking for prereleased packages... ? Select a new version (currently 0.0.0) Major (1.0.0) Changes: - hoho-lerna-core: 1.0.0 => 1.0.0 - hoho-lerna-module-a: 1.0.0 => 1.0.0 - hoho-lerna-module-b: 1.0.0 => 1.0.0 ? Are you sure you want to publish the above changes? Yes lerna info publish Publishing packages to npm... lerna info published hoho-lerna-module-b lerna info published hoho-lerna-core lerna info published hoho-lerna-module-a lerna info git Pushing tags... Successfully published: - hoho-lerna-core@1.0.0 - hoho-lerna-module-a@1.0.0 - hoho-lerna-module-b@1.0.0 lerna success publish finished
而后,npm registry里就多了3个垃圾package……
publish的大体过程是:
本地打个tag(例如
git tag v1.0.0
)自动更新依赖项版本号 示例
而后把各个package发布到npm
最后把tag和相应的commit给push上去
注意:若是发布到npm这一步失败了的话(好比没配置npm帐号),下一次直接lerna publish
没法直接发布,貌似由于本地tag已是v1.0.0认为上次发布成功了。把这个tag手动滚掉也不行,.git
里可能记了一些发布状态,滚掉以后出现commit hash匹配错误,这里不太友好
P.S.更多命令请查看Lerna
自动生成changelog
先安装changelog工具:
npm install lerna-changelog -g
而后在lerna.json
添加对应配置项:
"changelog": { "repo": "ayqy/hoho-lerna", "labels": { "enhancement": ":rocket: Enhancement", "bug": ":bug: Bug Fix", "doc": "Refine Doc", "feat": "New Feature" }, "cacheDir": ".changelog" }
特别注意:repo
是必填的,说是能自动推断,实际上不太靠谱,见The ‘repo’ field automatically inferred failed, but no error occurred
P.S.labels
里,key
是要在Github配置的标签,用来给Issue/PR分类,value
里的:bug:
只是调皮的emoji,会做为changelog里该类change的标题
到这里还不算完,还须要Github repo权限(为了能查Issue、PR),把token以环境变量的形式暴露出来(经常使用的话,能够添到~/.bash_profile
里):
export GITHUB_AUTH="..."
配置完毕。要达到“自动”,前提是平常开发维护遵照约定的规范,不然最后工具确定猜不出来changelog。规范是指:
(建议)commit message关联上对应的issue
(必须)建立PR时要选择咱们预约义的label
由于工具只整理github带有指定label的PR,并把commit message做为changelog项,建议commit message里关联上issue,生成的changelog就能关联到对应issue:
Uses github PR/Issue names categorized by labels with configurable headings.
例如:
git cm -m "feat: changelog, Close #1"
而后提交PR并给贴上label:feat
,merge以后,本地pull过来试试lerna-changelog
:
## Unreleased (2018-01-13) #### New Feature * [#2](https://github.com/ayqy/hoho-lerna/pull/2) feat: changelog, Closes [#1](https://github.com/ayqy/hoho-lerna/issues/1). ([@ayqy](https://github.com/ayqy)) #### Committers: 1 - 黯羽轻扬 ([ayqy](https://github.com/ayqy))
至关漂亮:https://github.com/ayqy/hoho-lerna/releases/tag/v1.1.0
P.S.应该在.gitignore
忽略掉本地生成的changelog临时文件,仅在发布新版本时本地lerna-changelog
,并把生成的changelog贴到release note。不自动发布release note多是API限制或出于慎重考虑,毕竟release note仍是比较重要的
另外,以这种方式自动整理出changelog,实际上靠的是开发中约束(PR的label规范,commit message做为changelog项的规范),与lerna
没有太大关系,只要是monorepo(Issue/PR)都放在一块儿,就能够按照这个思路获取Issue/PR信息,整理出changelog
至关于把最后梳理changelog的巨大工做量分布到平常开发维护了,change都要走PR,并且要有issue记录,不习惯的话仍是很麻烦的(有要求commit message自带label而不走PR的呼声,之后应该会支持)
四.适用场景
哪些场景能够采用monorepo(并用lerna管理?)?
不过度庞大的项目,整合到一块儿有100G源码的话,仍是再考虑一下吧
多模块/插件化项目,把官方维护的插件都做为package很是合适
另外,还须要:
基础建设
团队信任
基础建设是指强大的构建工具,能知足全部模块的build需求(纯前端项目的话,build压力不大)
monorepo环境下,能够而且鼓励改别人的代码,一方面须要持续集成机制(例如React – CircleCI)确认修改带来的影响,另外一方面还须要不一样团队之间互相信任,不然会常常出现一个团队的变动影响了另外一个团队的状况,须要回滚掉别人的修改,反而影响效率
P.S.Lerna出来好久了(和Babel差很少年纪),不少项目都在用了
参考资料
Lerna:很简练的官方文档
monorepo 新浪潮 | introduce lerna:前辈的helloworld还不错
REPO 风格之争:MONO VS MULTI
Mono Repository Tool Comparison:monorepo工具对比
New wave modularity with Lerna, monorepos, and npm organizations
本文分享自微信公众号 - 前端向后(backward-fe)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。