6

实践 lerna monorepo - rxliuli blog

 2 years ago
source link: https://blog.rxliuli.com/p/cd66150d2b86448590fcc9bb2419c0b2/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
  • 上古时期,前端没有工程化的概念可言,复用代码也不过是将某些 css、js 代码片段保存到笔记,需要时复制到项目中,仅此而已。参考:55 个提高你 CSS 开发效率的必备片段,或是 jquery 库
  • 莽荒时代,前端出现了 nodejs 和 npm,于是一大批通用代码被发布到了 npm 平台,可以在项目中简单配置即可使用通用的库,任何人都可以简单的将代码发布到 npm。参考:lodash
  • 现代,由于前端项目的复杂度逐渐上升,所以出现了 monorepo 工具以更简单的复用代码。例如层出不穷的 monorepo 支持工具 lerna@microsoft/rushyarn 2pnpmnpm 7

自去年 10 月开始,吾辈使用 lerna 重构个人和公司的项目,以应对愈加复杂的前端项目。

为什么需要 monorepo?

借用一下 lerna 官网的简介:

将大型代码仓库分割成多个独立版本化的 软件包(package)对于代码共享来说非常有用。但是,如果某些更改 跨越了多个代码仓库的话将变得很 麻烦 并且难以跟踪,并且, 跨越多个代码仓库的测试将迅速变得非常复杂。

为了解决这些(以及许多其它)问题,某些项目会将 代码仓库分割成多个软件包(package),并将每个软件包存放到独立的代码仓库中。但是,例如 Babel、 React、Angular、Ember、Meteor、Jest 等项目以及许多其他项目则是在 一个代码仓库中包含了多个软件包(package)并进行开发。

你可能会认为除了大型开源项目之外,monorepo 对于小型项目和生产环境的业务项目没有太多价值。但这是错的,前者我在微型工具库 liuli-util 上进行了实践,确定了它对于维护和使用确实有帮助。而后者,甚至出现了专门为业务项目的 monorepo 工具 @microsoft/rush,微软在 rushstack 项目中大规模使用了它。

为什么选择 lerna?

那么,有了这么多 monorepo 工具,为什么我们选择 lerna?

其实,除了 lerna 与 @microsoft/rush 之外,其它竞争对手都是包管理器,仅仅只是提供了 workspace 的工作空间,并未提供更高级功能。

lerna 和 @microsoft/rush 的 npm 趋势对比参考: https://www.npmtrends.com/lerna-vs-@microsoft/rush

下图是一个对比

对比项 lerna @microsoft/rush star 26,824 2,392 周下载 1,155,241 100,386 使用者 知名开源项目 微软系产品

就吾辈的实际使用体验而言,相比于 lerna,rush 默认包含了更多的东西,而非通过组合一系列可选的工具支持,这增长了相当的门槛。

下面是吾辈对其的一些认知过程

  • rush.js 是真的感觉很【专业】,限定了很多很多东西
  • https://rushjs.io/pages/maintainer/setup_policies/
  • 像是这里,通过 allowedPackagesPolicy 的方式对 team 中所有开发人员都可以直接引入新的 npm 包做出了限制
  • 唉,rush 比 lerna 复杂多了,做了很多很多的预定义的事情,这就意味着,它对项目维护者(而非开发者)的要求更高
  • 和 ide 没完全集成真痛苦.JPG
  • 吾辈总算明白这些配置为什么是【推荐配置】而不是【默认配置】了,引发的错误太多了(毕竟 npm 包很多并不规范)
  • rush monorepo 的一个问题是,某些包总喜欢强制指定依赖包的特定版本(例如 react-scripts),而 rush 总是“聪明”的仅安装最新的,导致添加的项目莫名其妙的炸掉
  • 吾辈的锅,它在最后给了方法 https://rushjs.io/pages/advanced/installation_variants/
  • 但一整个进阶主题都是在处理这个问题。。。
  • 算了,吾辈放弃了,rush + pnpm 感觉上维护配置成本太高了,滚回 lerna + yarn 了

rush 在功能、目标和文档方面更好,但现阶段而言还是 lerna 更成熟。

lerna 是什么?

简而言之,Lerna 是一个管理工具,用于管理包含多个软件包(package)的 JavaScript 项目。可以在一个项目中创建多个模块(基本上模块也可以认为是一个项目),并且可以在本地的模块之间互相关联。

lerna 项目的基本结构如下

  • 根目录
    • apps: 生产项目
      • app-1
      • app-2
    • libs: 通用模块
      • lib-1
      • lib-2
    • package.json
    • lerna.json
  • 根目录
    • libs: 模块根目录
      • lib-1
      • lib-2
    • package.json
    • lerna.json

目录的名字灵感来源于 rushstack

使用 lerna 的优点

其中部分优点是 monorepo 固有的优势,但也有 lerna 独有的功能。

  • 更容易抽离公共代码: 模块之间可以互相引用并且即时生效
  • 更容易统一
    • 项目配置: tsconfig.json/prettier.json/git hooks
    • 管理和发布一系列包: lerna publish
    • 修改依赖立刻生效: lerna bootstrap
    • 依赖版本: 和默认合并不同版本的依赖
    • 文档生成和合并: fliegdoc
    • 代码风格: prettier/git hooks
    • 在一个模块运行另一个模块的命令: lerna run <cmd> --scope <pkg>
    • 打包工具和流程: 封装更适合项目的打包 cli

目前稍微大点的开源项目不是已经转为了 lerna monorepo,就是已经在转换的路上(很像最近流行的使用 typescript 重构库)。包括但不限于以下这些:

吾辈目前使用的笔记工具 Joplin 也在去年使用 lerna 重构了,参考:Lerna migration

根据依赖图并行运行 npm 命令

1
lerna run <npm script> --include-dependencies --stream

参考: –stream–include-dependencies

git 规范

在单体项目中,只需要简单的分为 dev/master 即可开发,但在 monorepo 中,可能存在多个 apps,这种时候,简单的 dev/master 策略便不太好用了,主要原因是

  • dev 包含了所有的开发阶段的代码,所以合并的时候会合并到不希望合并的其他 apps 的修改
  • 提交记录看不出来是哪个分支的

吾辈的个人项目 joplin-utils 就面临这种问题。

下面是吾辈的一些想法,目前还正在实践中

  • 规范化分支
    • master: 生产环境分支,任何时候都应该是可部署的
    • dev: 指代正在开发环境进行测试的功能
    • feat-*: 正在开发的功能分支
    • fix-*: 修复线上 bug 的分支
  • 规范化流程
    • 分支一定是从 master 拉取
    • 分支一定是合并到 dev 测试
    • 分支一定是合并到 master 部署生产
  • 规范化提交信息
    • 基本采用 commitlint 控制提交格式,包括 类型(模块): 提交说明
  • 目录
    • apps: 最终用户可以使用的程序或 cli
    • libs: 一些依赖项,根据需要发布到 npm
    • examples: 一些示例项目
  • scripts
    • setup: 项目初始化的一些脚本
    • dev: 开发阶段运行的脚本
    • build: 打包代码
    • docs:dev: 启动本地文档预览服务
    • docs:build: 将文档捆绑为静态文件
    • docs:deploy: 部署文档到线上

rollup 捆绑 monorepo 仍然存在错误

目前 rollup + node-resolve 插件捆绑本地依赖时仍然存在一些问题,参考:https://github.com/rollup/plugins/issues/743,目前的替代方案是 esbuild

使用 lerna 虽然会增加一些复杂度,但带来的优点仍然是超过缺点的。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK