lerna入门指南

       感谢支持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命令处理依赖事后,会在moduleAnode_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的大体过程是:

  1. 本地打个tag(例如git tag v1.0.0

  2. 自动更新依赖项版本号 示例

  3. 而后把各个package发布到npm

  4. 最后把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。规范是指:

  1. (建议)commit message关联上对应的issue

  2. (必须)建立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

联系ayqy      

若是在文章中发现了什么问题,请查看原文并留下评论,ayqy看到就会回复的(不建议直接回复公众号,看不到的啦)

特别要紧的问题,能够直接微信联系ayqywx      


本文分享自微信公众号 - 前端向后(backward-fe)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。

相关文章
相关标签/搜索