bit 专题:由组件复用到 bit 适用场景

1,561 阅读7分钟

组件复用进化史

Ctrl C & Ctrl V

总听见有人戏谑的讲出 Ctrl C & Ctrl V 大法好,并自称为“搬砖工程师”——殊不知这 CV 大法,其实是最朴素而原始的组件源码级复用方式

朴素,意味着这是一种集:

  • 0 学习成本、0 技术壁垒
  • 任意 Repo 复用
  • 任意粒度复用
  • Writeable

优点一身的利器;而因为原始,又充斥着够痛的槽点:

  • 缺少 VCS
  • 缺少依赖管理

后来, CV 大法进化的一种折衷形态是——把各种可复用的 Utils、Widget 代码放【拷贝、打包】到专门的 Repo、Asset 里,比如 CDN 上的 jQuery、支持选择下载的 Tangram——选择性的解决了一些槽点,也丢失了一些优点

Node Module

NodeJS 的时代,彻底被颠覆的前端生态——组件复用的高级形态 Node Module

我不确定,有多少的 Utils、Widget 组件直接一开始就是单独的 Repo——其实可能更多的组件,最初是和业务 Repo A 在一起, 而凑巧的是在 Repo B 里也能用上这些组件

在 npm 的时代,可能就需要需要 XVCtrl X & Ctrl V】,从 Repo A 到单独的 Node Module Repo,然后再 Repo A、Repo B 里通过 npm 引入任意的 Node Module VCS

其中优点:

  • 文件粒度复用
  • VCS
  • 依赖管理完备
  • 学习成本较低

槽点:

  • 需要专门拆分 Repo【假定组件皆源于业务】
  • Readonly

Git Submodule

Submodule 能将多个 Repo 形式上整合在一个 Repo——一种原始形态的类 Monorepo、直接复用源码的方式;等效的,还有更原始、却更方便的 ln -s 软链接

其显著的优点:

  • VCS
  • Writeable

其明显的槽点:

  • 需要拆分多个 Repo
  • 有一定学习和操作成本

Monorepo

Node Module 生态下的 Monorepo 是真正意义上的把多 Repo 合并成一个 Repo

其优势:

  • Node Module
  • 1 个 Repo
  • Repo 内 Writeable

Monorepo 集成了所有的优势,尤其适合维护多个源码层面彼此相关,功能却又比较独立、完整的 Node Module 或者业务 Module,对应的技术方案有,如适合维护 Mono Node Module 的 Lerna,以及 Mono Business Module 的 NX 等

痛点:

  • VCS 提交记录会变得比较复杂——如果仅为了组件复用,整合业务 Repo,成本收益 可能还不如使用 Submodule
  • Monorepo 以外 Readonly,本质上依旧是 Node Module
  • Monorepo 管理 Module 的成本还是比较高的,本质还是一个个 Node Module,需要对应的依赖、版本管理
  • 比较高的学习、维护成本
  • 此外,不是所有 Module 都适合放在同一个 Monorepo

bit 适用场景

经过客观的回顾【主观的踩】后,终于切入正题《什么场景适用 bit》——为了不那么具有攻击性和胁迫意味,我把主题从《为什么使用 bit》给改了过来

本质

初识者,往往会 bit、git 傻傻不分,除去 bit 最小存储单位、象征组件细粒度的本身含义,官方在在命名上肯定也有故意撞车 git 之嫌

bit 在 Repo 之上添加了文件到组件映射的语义层,构成了一套独立的类似 git 的 VCS

本地,默认情况下,在 .git 目录下会有一个 .bit 目录存储;远端的 bit server 其实就是依赖于 git 实现的

关键特性-优点

  • 可直接从已有项目、库内导出组件
  • 可在任意使用到组件的应用修改组件源代码
  • 可以将组件的定制修改直接回馈给源组件
  • 自动将组件包裹成 Node Module
  • 细粒度

适应场景举例

1. 直接组件复用

设想在 Recruit Repo 里有维护一个符合 bit 组件规范 方的 Avatar 组件,然后再新开的 Admin Repo 里也需要用到这样一个 UI 一致的 Avatar 组件,比如这样:

然后:

  1. 2020 了,还要 Ctrl C & Ctrl V ???
  2. 拆分一个单独的 Node Module【Repo】 ???
  3. 把 Recruit Repo 和 Admin Repo 放一个 Monorepo ???

这么一对比,最适合的办法居然还是 CV——

这样的场景,可以使用 bit 来更优雅的解决:

在 Recruit Repo 里,添加并导出 Avatar 组件,bit 会自动处理依赖、将 Avatar 组件包装成一个 Node Module

	bit init
    bit add avatar
    bit tag
    ...
    bit export

在 Admin Repo 里,通过 bit 引入 Avatar 组件,bit 会自动以 npm + ln 的形式,把 Avatar 组件安装到 node_modules 下,跟其他普通的 node module 没有本质的区别

	bit init
    ...
    bit import avatar

2. 需要定制修改

当 Admin Repo 需要一个圆形的、但是源组件是方形的 Avatar 组件,同时兼顾 Admin Repo 同步Recruit Repo 内变动的能力

这样似乎就只有 CV 可供选择,兼顾定制化与可人工同步变动的能力——

这样的场景,可以使用 bit 来更优雅的解决:

在 Admin Repo 里,引入 Avatar 组件——源码,进行任意的修改,并将改动提交到 Admin Repo 的 VCS

	bit import avatar
    改吧改吧
    git add ...

并当 Recruit Repo 导出 Avatar 组件的新版本的时候,通过 bit 同步并合并变动

	bit import avatar --merge

更多见 bit 工作流

3. 需要将改动分享到源组件

Admin Repo 同学发现并修复了 Avatar 组件的一个 bug,这个时候:

  • 是告诉 Recruit Repo 同学如何手动再修复一遍这个 bug???
  • 还是 Admin Repo 同学给 REcruit Repo 提一个 pr ???

除了源 Recruit Repo,如果还有 X1 Repo、X2 Repo 也用到了 Avatar 组件,无论人工同步修复,还是 pr,好像都不是那么顺畅——

这样的场景,可以使用 bit 来更优雅的解决:

在 Admin Repo 以及其他任意消费 Avatar 组件的 Repo【不要将组件添加到 Repo 的 VCS】,可以修复 bug、新增 feature 到 Avatar 组件,然后通过 bit 发布新的版本,并推送到远端 bit server

	改吧改吧
    bit tag 
    bit export

在 Recruit Repo 里,通过 bit 同步来自 Avatar 组件消费者的变动

	bit import --merge

更多见 bit 工作流

4. 细粒度与 MonoRepo

设想,有维护一个专门组件库 Antd Repo,就像 antd 那样一个 node module 包含了几十个组件,这样可以很省事的开发、维护——

但大块头也有以下明显的痛点:

  • 只能几十个组件整体发布
  • 整体安装
  • 整体引用——为了按需打包,还专门写了一个 babel-import-plugin

为此,我们会首选引入 Monorepo,比如说 lerna,来解决这些痛点——大块头的痛点确实也被解决了,几十个组件被拆成 Monorepo 里几十个独立的 packages,这项浩瀚的工程,虽然可以通过 CLI 命令行减少一些模板性质的重复劳动,但依赖管理、文件结构改造依旧是很繁琐的【从零开始的 Repo 不会繁琐的改造,繁琐的日积月累反倒不像一个真正的问题】

这里 MonoRepo 的痛点并不那么明显,bit 未必就能更优雅一些——比如 lerna 和 bit 都有较高的学习成本、相似的操作成本,唯一 bit 占优的地方就是:

  • 因为 bit 已经承包依赖管理,可以不用那么关注组件的依赖,尤其组件相互的依赖
  • 不再要求 node module 标准的目录结构

用与不用的选择

凡事有两面,工具也有两面,bit 推出的时间不算短,但其实一直使用的人并不太多,处于不温不火的局面

bit 的痛点:

  • 学习心智,bit、git 傻傻不清,“雷同”的 CLI 命令偏偏还有些微的差异,很容易混淆【我司内部的 KBit 可以了解一下,NodeJS 层对 bit 进行了比较友好的封装】
  • 操作成本,bit 已然算是独立 VCS、package manager 体系,所以在 git、npm 之外会有额外的操作成本

bit 当然是能解决实际应用的中的痛点,但这个痛点是不是够痛、是不是有还可以将就用的办法,可能就是决定用与不同的选择依据了

以上文字,以个人的直观经历和思考汇总而得,如有谬误欠妥之处,恭请指正