前言:咱们运用微前端架构解决了应用体积庞大的问题,经过实践微前端的理念,将前端应用拆分为多个微应用(可独立部署、松散耦合的应用)。同时微应用的存在,使得咱们无需在构建一个庞大的应用,而是按需构建,极大了加快了构建效率。但只是解决了应用层面的问题,在中后台应用场景中,不一样微应用和基座之间可能存在通用的模块依赖,那么若是应用间能够实现模块共享,那么能够大大优化单应体积大小html
最简单的方式,就是把须要共享的模块抽出,多是一个工具库,有多是一个组件库,而后讲其打包成为npm包,而后在每一个子应用中都安装该模块依赖,以此达到多个项目复用的效果前端
也就表明每一个应用都有相同的npm包,本质上没有真正意义上的实现模块共享和复用,只是代码层次共享和复用了,应用打包构建时,仍是会将依赖包一块儿打包vue
劣势有如下👇 几点:node
npm包
进行更新发布了,微应用还须要从新构建,调试麻烦且低效 (除非用npm link
)阿乐童鞋: 那若是咱们没有搭建npm内网,又不想把模块开源出去,并且依赖npm,只要涉及变动须要从新发布,有没有其余方式能够解决以上问题呀?react
你能够试试 Git Submodule ,它提供了一种相似于npm package的依赖管理机制,二者差异以下图所示👇webpack
经过在应用项目中,经过git submodule add <submodule_url>
远程拉取子模块项目,这时会发现应用项目中多了两个文件.gitmodules
和子模块目录
git
这个子模块就是咱们共享的模块,它是一个完整的Git
仓库,换句话说:咱们在应用项目目录中不管使用git add/commit
都对其不影响,即子模块拥有自身独立的版本控制github
总结: submodule
本质上是经过git submodule add把项目依赖的模块加起来,最终构成一个完整的项目。并且add进来的模块,项目中并不实际包含,而只是一个包含索引信息,也就是上文提到的 .gitmodule
来存储子模块的联系方式
, 以此实现同步关联子模块。当下载到本地运行的时候才会再拉取文件web
部分命令行:vue-router
git submodule add <子模块repository> <path>
: 添加子模块
git submodule update --recursive --remote
: 拉取全部子模块的更新
阿乐童鞋: 🌲 树酱,我记得有个叫
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进行落地实际,目前基于微前端架构中后台应用存在依赖重叠过多的状况,后期会经过实践来深刻分享
咱们知道
webpack
中有externals
的配置,主要是用来配置:webpack输出的bundle中排除依赖,换句话说经过在external定义的依赖,最终输出的bundle不存在该依赖,主要适用于不须要常常打包更新的第三方依赖,以此来实现模块共享。
下面是一个vue.config.js 的配置文件,经过配置exteral移除不常常更新打包的第三方依赖👇
你能够经过在packjson中script定义的命令后添加--report
查看打包📦后的分析图,若是是webpack就是用使用插件webpack-bundle-analyzer
阿乐童鞋: 🌲 树酱,那移除了这些依赖以后,如何保证应用正常使用?
浏览器环境:咱们使用cdn的方式在入口文件引入,固然你也能够预先打包好,好比把vue全家桶打包成vue-family.min.js
文件,最终达成多应用共享模块的效果
<script src="<%= VUE_APP_UTILS_URL %>static/js/vue-family.min.js"></script>
总结:避免公共模块包(package) 一块儿打到bundle 中,而是在运行时再去从外部获取这些扩展依赖
经过这种形式在微前端基座应用加载公共模块,并将微应用引用一样模块的external移除掉,就能够实现模块共享了 可是存在微应用技术栈多样化不统一的状况,可能有的使用vue3,有的使用react开发,但externals 并没有法支持多版本共存
的状况,针对这种状况该方式就不太适用
官方介绍:"DLL" 一词表明微软最初引入的动态连接库, 换句话说个人理解,能够把它当作缓存,经过预先编译好的第三方外部依赖bundle,来节省应用在打包时混入的时间
Webpack DLL 跟 上一节提到的external本质是解决一样的问题:就是避免将第三方外部依赖打入到应用的bundle中(业务代码),而后在运行时再去加载这部分依赖,以此来实现模块复用,也提高了编译构建速度
webpack dll模式下须要配置两份webpack配置,下面是主要两个核心插件
DllPlugin
:在一个独立的webpack进行配置webpack.dll.config.js
,目的是为了建立一个把全部的第三方库依赖打包到一块儿的bundle的dll文件里面,同时还会生成一个manifest.json
的文件,用于:让使用该第三方依赖集合的应用配置的DllReferencePlugin能映射到相关的依赖上去
具体配置看下图👇
DllReferencePlugin
:插件核心是把上一节提到的经过webpack.dll.config.js中打包生成的dll文件,引用到须要实际项目中使用,引用机制就是经过DllReferencePlugin插件来读取vendor-manifest.json文件,看看是否有该第三方库,最后经过add-asset-html-webpack-plugin
插件在入口html自动插入上一节生成的vendor.dll.js
文件, 具体配置看下图👇
模块联邦是 Webpack5 推出的一个新的重要功能,能够真正意义上实现让跨应用间作到模块共享,解决了从前用 NPM 公共包方式共享的不便利,同时也能够做为微前端的落地方案,完美秒杀了上两节介绍webpack特征
用过qiankun
的小伙伴应该知道,qiankun微前端架构控制的粒度是在应用层面
,而Module Federation控制的粒度是在模块层面
。相比之下,后者粒度更小,能够有更多的选择
与qiankun等微前端架构不一样的另外一点是,咱们通常都是须要一个中心基座去控制微应用的生命周期,而Module Federation则是去中心化的,没有中心基座的概念,每个模块或者应用都是能够导入或导出,咱们能够称为:host和remote
,应用或模块便可以是host也能够是remote,亦或者二者共同体
看看下面这个例子👇
核心在于 ModuleFederationPlugin中的几个属性
remote
: 示做为 Host 时,去消费哪些 Remote;exposes
:表示做为 Remote 时,export 哪些属性提供给 Host 消费shared
: 可让远程加载的模块对应依赖改成使用本地项目的 vue,换句话说优先用 Host 的依赖,若是 Host 没有,最后再使用本身的后期也会围绕 Module Federation 去作落地分享
🌲 推荐阅读:
你好,我是🌲 树酱,请你喝杯🍵 记得三连哦~
1.阅读完记得点个赞哦,有👍 有动力
2.关注公众号:前端那些趣事,陪你聊聊前端的趣事
3.文章收录在Github frontendThings 感谢Star✨
复制代码