前言:我们运用微前端架构解决了应用体积庞大的问题,通过实践微前端的理念,将前端应用拆分为多个微应用(可独立部署、松散耦合的应用)。同时微应用的存在,使得我们无需在构建一个庞大的应用,而是按需构建,极大了加快了构建效率。但只是解决了应用层面的问题,在中后台应用场景中,不同微应用和基座之间可能存在通用的模块依赖,那么如果应用间可以实现模块共享,那么可以大大优化单应体积大小
1.Npm 依赖
最简单的方式,就是把需要共享的模块抽出,可能是一个工具库,有可能是一个组件库,然后讲其打包成为npm包,然后在每个子应用中都安装该模块依赖,以此达到多个项目复用的效果
也就代表每个应用都有相同的npm包,本质上没有真正意义上的实现模块共享和复用,只是代码层次共享和复用了,应用打包构建时,还是会将依赖包一起打包
劣势有以下👇 几点:
- 每个微应用都会打包该模块,导致依赖的包冗余,没有真正意义上的共享复用
- 当
npm包
进行更新发布了,微应用还需要重新构建,调试麻烦且低效 (除非用npm link
)
2.Git Submodule (子模块)
阿乐童鞋: 那如果我们没有搭建npm内网,又不想把模块开源出去,而且依赖npm,只要涉及变更需要重新发布,有没有其他方式可以解决以上问题呀?
2.1 对比 npm
你可以试试 Git Submodule ,它提供了一种类似于npm package的依赖管理机制,两者差别如下图所示👇
2.2 如何使用
通过在应用项目中,通过git submodule add <submodule_url>
远程拉取子模块项目,这时会发现应用项目中多了两个文件.gitmodules
和子模块目录
这个子模块就是我们共享的模块,它是一个完整的Git
仓库,换句话说:我们在应用项目目录中无论使用git add/commit
都对其不影响,即子模块拥有自身独立的版本控制
总结: submodule
本质上是通过git submodule add把项目依赖的模块加起来,最终构成一个完整的项目。而且add进来的模块,项目中并不实际包含,而只是一个包含索引信息,也就是上文提到的 .gitmodule
来存储子模块的联系方式
, 以此实现同步关联子模块。当下载到本地运行的时候才会再拉取文件
部分命令行:
git submodule add <子模块repository> <path>
: 添加子模块git submodule update --recursive --remote
: 拉取所有子模块的更新
2.3 Monorepo
阿乐童鞋: 🌲 树酱,我记得有个叫
Monorepo
又是什么玩意,跟 Git Submodule 有啥区别?
Monorepo 全称叫monolithic respoitory
,即单体式仓库,核心是允许我们将多个项目放到同一个仓库里面进行管理。主张不拆分repo,而是在单仓库里统一管理各个模块的构建流程、版本号等等
这样可以避免大量的冗余node_module冗余,因为每个项目都会安装vue、vue-router等包,再或者本地开发需要的webpack、babel、mock等都会造成储存空间的浪费
那么Monorepo是怎么管理的呢? 开源社区中诸如babel、vue
的项目都是基于Monorepo去维护的(Lerna工具)
我们以Babel为例,在github中可以看到其每个模块都在指定的packages目录下, 也就意味着将所有的相关package都放入一个repository来管理,这不是显得项目很臃肿?
也就这个问题,啊乐同学和啊康同学展开了辩论~
最终是选用
Monorepo
单体式仓库还是Multirepo
多仓库管理, 具体还是要看你业务场景来定,Monorepo集中管理带来的便利性,比如方便版本、依赖等管理、方便调试,但也带来了不少不便之处 👇
- 统一构建工具所带来更高的要求
- 仓库体积过大,维护成本也高
🌲 酱 不小心扯多了,还有就是Monorepo 跟 Git Submodule 的区别
- 前者:monorepo在单repo里存放所有子模块源码
- 后者:submodules只在主repo里存放所有子模块“索引”
目前内部还未使用Monorepo进行落地实际,目前基于微前端架构中后台应用存在依赖重叠过多的情况,后期会通过实践来深入分享