背景
对于维护过多个package的同学来说,都会遇到一个选择题,这些package是放在一个仓库里维护还是放在多个仓库里单独维护,数量较少的时候,多个仓库维护不会有太大问题,但是当package数量逐渐增多时,一些问题逐渐暴露出来:
- package之间相互依赖,开发人员需要在本地手动执行
npm link
,维护版本号的更替。 - issue难以统一追踪,管理,因为其分散在独立的repo里。
- 每一个package都包含独立的
node_modules
,而且大部分都包含babel
,webpack
等开发时依赖,安装耗时冗余并且占用过多空间。
解决
上述提到的多package项目,实际上是比较常见的,在日常业务中,开发UI组件库、Util工具库以及插件库等场景会和上述仓库类似。接下来,我们来看一下几个明星仓库的目录结构。
根据上述截图,我们可以发现这些仓库之间的共性:
- 均使用单个仓库来管理多个package
- 多个package之间可能存在相互依赖的情况
为了降低多package项目的维护成本,我们使用lerna作为流程管理工具。
使用lerna提升开发流程体验
接下来,我们从一个demo出发,了解基于lerna的开发流程。
项目初始化
我们需要维护一个UI组件库,其包含2个组件,分别为House(房子)和Window(窗户)组件,其中House组件依赖于Window组件。
我们使用lerna初始化整个项目,并且在packages
里新建了2个package
,执行命令进行初始化:
lerna init复制代码
初始化化后目录结构如下所示:
.
├── lerna.json
├── package.json
└── packages
├── house
│ ├── index.js
│ ├── node_modules
│ └── package.json
└── window
├── index.js
├── node_modules
└── package.json复制代码
增加依赖
接下来,我们来为组件增加些依赖,首先House组件不能只由Window构成,还需要添加一些外部依赖(在这里我们假定为lodash)。我们执行:
lerna add lodash --scope=house复制代码
这句话会将lodash
增添到House的dependencies
属性里,这会儿你可以去看看package.json
是不是发生变更了。
我们还需要将Window添加到House的依赖里,执行:
lerna add window --scope=house复制代码
就是这么简单,它会自动检测到window隶属于当前项目,直接采用symlink
的方式关联过去。
symlink:符号链接,也就是平常所说的建立超链接,此时House的node_modules里的Window直接链接至项目里的Window组件,而不会再重新拉取一份,这个对本地开发是非常有用的。
发布到npm
接下来我们只需要简单地执行lerna publish
,确认升级的版本号,就可以批量将所有的package发布到远程。
默认情况下会推送到系统目前npm对应的registry里,实际项目里可以根据配置leran.json
切换所使用的npm客户端。
更新模块
接下来,我们变更了Window组件,执行一下lerna updated
,便可以得知有哪些组件发生了变更。
→ lerna updated
lerna info version 2.9.1
lerna info Checking for updated packages...
lerna info Comparing with v1.0.9.
lerna info Checking for prereleased packages...
lerna info result
- jx-house
- jx-window复制代码
我们可以看到,虽然我们只变更了window组件,但是lerna
能够帮助我们检查到所有依赖于它的组件,对于没有关联的组件,是不会出现在更新列表里的,这个对于相比之前人工维护版本依赖的更新,是非常稳健的。
集中版本号或独立版本号
截止目前,我们已经成功发布了2个package,现在再新增一个Tree
组件,它和其他2个package保持独立,随后我们执行lerna publish
,它会提示Tree组件的版本号将会从0.0.0
升级至1.0.0
,但是事实上Tree组件仅仅是刚创建的,这点不利于版本号的语义化,lerna
已经考虑到了这一点,它包含2种版本号管理机制。
fixed
模式下,模块发布新版本时,都会升级到leran.json
里编写的version
字段independent
模式下,模块发布新版本时,会逐个询问需要升级的版本号,基准版本为它自身的package.json
,这样就避免了上述问题
如果需要各个组件维护自身的版本号,那么就使用independent
模式,只需要去配置leran.json
即可。
总结
lerna
不负责构建,测试等任务,它提出了一种集中管理package的目录模式,提供了一套自动化管理程序,让开发者不必再深耕到具体的组件里维护内容,在项目根目录就可以全局掌控,基于npm scripts
,可以很好地完成组件构建,代码格式化等操作,并在最后一公里,用lerna变更package版本,将其上传至远端。
如果你有类似的项目,那么现在是时候尝试用lerna做优化了。