微前端工具箱:用subtree解决多模块复用问题

653ca8779c7bb88a76ea8bf50118e29e.png

在日常开发工作中,可能会面临这样一种需求:项目 A 中,存在一个或多个有价值的功能模块,这里的所谓模块指有一个或几个页面组成的功能模组;其他项目,如项目 B,也想借助这些模块给自己赋能,且基本要求如:

  • 要使用项目 B 自己的导航菜单

  • 要重新定义路由并将各个模块分散到不同页面下

  • 接口请求要统一加特殊标识参数

  • 项目 B 要根据额外的环境变量对各模块中的功能做限制

  • 项目 B 希望以自己的上线节奏更新模块

df74d6f523ceb6ebfdeb723e30e066be.png

为了理解方便,约定文档中可能通用的几个称呼:

  • 主项目 - 项目 A

  • 新项目 - 项目 B 等

  • 子模块 - 从项目 A 里划分出的几个模块

【方案对比】

经过调研,常用且纯前端的项目模块化改造方案如下:

成本 \ 方案iframe微前端npm包Git子模块
首次改造主项目3355
首次改造新项目1322
维护子模块2332
更新子模块1531
同步子模块1121
总开发成本8161511

综合到考虑各业务项目体量、具体产品需求,和由改造带来的长期用户体验等,我们可能会在工具箱中选择Git子模块方案进行。

【git subtree 介绍】

subtree 是 git submodule 技术的主要替代技术,避免了后者的一些麻烦。

具体介绍这里不做赘述,可以直接参考文末的资料,如 《submodule vs. subtree 对比》[1]

简而言之:

  • 为每个子模块创建一个独立的 git 仓库

  • 子模块的 git 仓库中的文件可以被当成一个普通的子目录添加到主项目/新项目中

  • 过程中只拉取文件,不会产生额外的 git 隐藏文件等

  • 子模块中的改变会被正常提交到所在项目的历史中

  • 在主项目/新项目层面也可完成子模块的 git 推送/拉取操作,这也是推荐的做法

分别在主项目/新项目中执行的 git 命令:

  • 添加 remote 以简化后续命令:

git remote add -f <子模块别名> git@coding.foo.com:<子模块的...`.git`>

后面以 子模块别名report 为例

  • 添加 subtree:

git subtree add --prefix=<相对路径> report <分支> --squash
  • 拉取 subtree:

git subtree pull --prefix=<相对路径> report <分支> --squash
  • 推送 subtree:

git subtree push --prefix=<相对路径> report <分支>
  • 查看 subtree 的 id:

git ls-remote report
或
git ls-remote report | grep <sha-1>

【选择一种分支策略】

和 git 本身各种流派的 workflow 一样,subtree 并没有规定特定的工作流程;这里尝试总结两种:

⇲ 单向模式:被动小分支

  • 涉及子模块中功能升级、优化、改进的内容,都在主项目中

  • 日常的以上改动都 push 到子模块的 master

  • 子模块仓库中维护某个独立分支,如用于项目 B 的 feature-projB

  • 子模块 master 有更新时手动 merge 到 feature-projB

  • 新项目只 pull 最新的 feature-projB

优点:
  1. 新项目可以随意修改特定的子模块分支

  2. 合并冲突可以在子模块中按普通方式解决

  3. 子模块代码中无需判断所在项目的环境

缺点:
  1. 如果改动需要反向同步到 master,可能需要额外的重复修改或 cherry-pick

♺ 双向模式:共建master

  • 主项目和新项目各自维护涉及子模块的相关功能

  • 新项目中的改动也可以 push 到子模块的 master

  • 新项目涉及子模块的改动应保证不污染主项目等其他项目

优点:
  1. 涉及子模块中功能升级、优化、改进的内容,可以由各个业务项目共同贡献

  2. 如果改动不复杂可以跳过再去子模块仓库下进行的各种操作

缺点:
  1. 可能需要改动 webpack 配置等以区分项目环境

  2. 代码中需要区分环境的片段需要重点关注

【注意问题】

  • 新项目和主项目结构、基础能力难免不一致,如 src/storesrc/common/store ,以及 http 等模块中方法的不同

    • 要竭尽所能地使子模块低耦合,保证多项目适配的基本可行性

    • 要在文档中(如子模块根目录的README)标明所有依赖点

  • merge 代码冲突

    • 双向模式下,如果本方没有更新,可以直接 rm -rf 掉子模块目录并重新 add

【参考文档】

[1]

《submodule vs. subtree 对比》: https://einverne.github.io/post/2020/04/git-subtree-usage.html#sub-module-vs-sub-tree-%E5%AF%B9%E6%AF%94

  • https://betterprogramming.pub/git-subtree-usage-6aaba8b5d947

  • https://medium.com/@v/git-subtrees-a-tutorial-6ff568381844

  • https://medium.com/@porteneuve/mastering-git-subtrees-943d29a798ec

  • https://medium.com/codex/github-subtrees-fb93d229cdc0

  • https://segmentfault.com/a/1190000012002151

  • https://tech.youzan.com/git-subtree/

  • http://www.fwolf.com/blog/post/246

  • https://liuyufang.com/version-control/git/git-subtree

  • https://www.worldhello.net/gotgit/04-git-model/050-subtree-model.html

989235ad52761f89b735db5d234da35e.png

9b71cfa53fedbb6440ecb61727c8a6b6.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值