跳到主要内容

模块联邦

模块共享之痛​

对于一个互联网产品来说,一般会有不同的细分应用,比如腾讯文档可以分为word、excel、ppt等等品类,抖音 PC 站点可以分为短视频站点、直播站点、搜索站点等子站点,而每个子站又彼此独立,可能由不同的开发团队进行单独的开发和维护,看似没有什么问题,但实际上会经常遇到一些模块共享的问题,也就是说不同应用中总会有一些共享的代码,比如公共组件、公共工具函数、公共第三方依赖等等。对于这些共享的代码,除了通过简单的复制粘贴,还有没有更好的复用手段?

复用手段历史解决方案,主要包括发布 npm 包、Git Submodule、依赖外部化 + CDN 导入和 Monorepo 架构

发布 npm 包​

发布 npm 包是一种常见的复用模块的做法,我们可以将一些公用的代码封装为一个 npm 包

封装 npm 包可以解决模块复用的问题,但它本身又引入了新的问题:

  • 开发效率问题。每次改动都需要发版,并所有相关的应用安装新依赖,流程比较复杂

  • 项目构建问题。引入了公共库之后,公共库的代码都需要打包到项目最后的产物后,导致产物体积偏大,构建速度相对较慢

因此,这种方案并不能作为最终方案

Git Submodule​

submodule允许你将一个Git 仓库当作另外一个Git 仓库的子目录

通过 git submodule 的方式,我们可以将代码封装成一个公共的 Git 仓库,然后复用到不同的应用中,但也需要经历如下的步骤

  • 公共库 lib1 改动,提交到 Git 远程仓库;
  • 所有的应用通过git submodule命令更新子仓库代码,并进行联调

整体的流程其实跟发 npm 包相差无几,仍然存在 npm 包方案所存在的各种问题。

缺点:

  • cicd持续集成的时候,需要注意的是, 需要拉去最新的子仓库的代码
  • 更新子仓库代码时候,每个应用都需要更新子仓库

Monorepo​

作为一种新的项目管理方式,Monorepo 也可以很好地解决模块复用的问题。在 Monorepo 架构下,多个项目可以放在同一个 Git 仓库中,各个互相依赖的子项目通过软链的方式进行调试,代码复用显得非常方便,如果有依赖的代码变动,那么用到这个依赖的项目当中会立马感知到

缺点:

  • 所有的应用代码必须放到同一个仓库。如果是旧有项目,并且每个应用使用一个 Git 仓库的情况,那么使用 Monorepo 之后项目架构调整会比较大,也就是说改造成本会相对比较高。
  • Monorepo 本身也存在一些天然的局限性,如项目数量多起来之后依赖安装时间会很久、项目整体构建时间会变长等等,我们也需要去解决这些局限性所带来的的开发效率问题。而这项工作一般需要投入专业的人去解决,如果没有足够的人员投入或者基建的保证,Monorepo 可能并不是一个很好的选择。
  • 项目构建问题。跟 发 npm 包的方案一样,所有的公共代码都需要进入项目的构建流程中,产物体积还是会偏大

vite模块联邦​

  • vite-plugin-federation 插件,这是社区提供了一个比较成熟的vite模块联邦方案
  • 支持vite/rollup

使用​

  • 使用Module Federation通常需要2个以上的工程,一个作为Host端【本地端】,一个作为Remote端 【远程端】

需要注册配置 远程模块和本地模块

模块联邦实现​

实现模块联邦的三大主要:

  1. Host模块: 即本地模块,用来消费远程模块。
  2. Remote模块: 即远程模块,用来生产一些模块,并暴露运行时容器供本地模块消费。
  3. Shared依赖: 即共享依赖,用来在本地模块和远程模块中实现第三方依赖的共享