ModuleFederation是啥?
Module Federation便是一个JavaScript远程模块加载架构,即:Module federation allows a JavaScript application to dynamically run code from another bundle/build, on both client and server。
它准许将一个应用程序的某些模块打包为一个独立的、可远程加载的 bundle,并在运行时动态地加载这些模块。这般,在另一个应用程序中就能够经过远程容器加载这些模块,并直接运用它们。这种方式能够避免重复打包和加载相同的模块或库,加强了应用程序的性能和效率。
复习一下核心概念:
module
:每一个源码js文件其实都能够看成一个module
chunk:每一个打包落地的js文件其实都是一个chunk,每一个chunk都包括非常多module
本地模块即为普通模块,是当前构建的一部分;
远程模块不属于当前构建,并在运行时从所说的容器加载。
意见读一下:《探索webpack5新特性Module federation在腾讯文档的应用》、《一文通透讲解webpack5 module federation》、《一文看透 Module Federation 下》
mf供给的能力便是把每一个应用中能够共用的component或library提取出来,安排到应用集群中,每一个应用能够引用其他应用暴露出来的模块,自己亦能被其他应用引用,这就实现了一个去中心化的应用安排集群。
在 webpack 的构建中,每一个构建结果其实都是隔离的,那样它是怎样打破这个隔离,实现应用间共享依赖呢?
关键在于 sharedScope,共享功效域,在 Host 和 Remote 应用之间创立一个可共享的 sharedScope,它包括了所有可共享的依赖,大众都按必定规则往 sharedScope 里获取对应的依赖。
Module Federation 基于 webpack 的远程容器特性
,详见:https://www.webpackjs.com/concepts/module-federation/#dynamic-remote-containers
ModuleFederation为么而生?
webpack和npm几乎形成为了完美搭档的状态,但前端本来从cdn获取的资源改由打包工具合并到一个包体里带来了致命的更新和安排效率问题。
在某些需要需要动态更新的场景,这种all in one的打包机制让包体的安排效率大打折扣,这本不是webpack和npm的问题,而是人们天生对web环境需要快速迭代、快递实验的高需求带来的典型场景需要。
注:externals 本身不可彻底处理动态更新的诉求,只适合于将底层公关依赖包体外链到cdn
同期webpack随着项目体积日趋庞大,新的问题诸如研发体验差(热更新慢)、包体加大、构建速度慢(node_modules黑洞)等问题亦诞生了,此时新生代的研发工具snow和vite以不打包的名义起始蚕食webpack的市场。
她们都利用了浏览器的原生模块化能力esm,跳过webpack的需要的依赖分析和打包流程,这里设计下做到了毫秒级的调试起步。
模块联邦因此呢诞生了,它的伟大之处在于保持当前前端研发模块化、组件化、工程化的有效率体系下,准许模块独立研发、独立安排,经过 CDN 直接共享,从而挣脱npm包体没法动态更新的桎梏,从而推动全部前端界研发和运行体验提升到一个新高度。
只要有越多的模块能提高到联邦里,本地起步速度将越快!
远程模块能够做为微模块(模块级别的微前端),是页面级别的微前端的一种弥补,由于页面级别的微前端,如 qiankun、无界等,它们的粒度太粗了,有时候需要更细粒度的微前端,例如:组件、函数级别的。这种场景,就能够运用远程模块,来实现微模块的效果。
容器型微前端
咱们把以single-spa为表率的这一类方法统叫作为微容器,在single-spa走红之后市面非常多基于single-spa二次封装的库如雨后春笋般涌出,典型的表率作如阿里的qiankun,意在处理有些single-spa未处理的问题并让其更适合企业级研发,同期亦诞生了非常多非singlespa系的框架,如京东的micro-app、腾讯的wujie等,它们的细节实现各有差异,包括js沙箱隔离、css隔离、iframe编排、启用web-component、window代理、接入过程等各个地区的细节亦各有千秋,但它们都一个很明显的特点,对应的模块粒度是全部应用,做出的制品能够理解为一种以宏观态的方式来组合多个应用交付给用户运用
。
试想一下,你不会极端到以运行时隔离的方式去渲染多个按钮吧?
模块型微前端
相较于微容器宏观态的组合应用方式,微模块则能够形容为微观态的组合方式,它的粒度更小,小到能够是一个函数,一个基本的组件,针对研发者来讲,引入微模块和引入一个普通的js包无任何区别,她们在运用上亦并无任何区别,但恰恰是这一点!是它和微容器最大差异之一,微模块的运用方式回归到了js语法本身。
这般,微前端就变为:管好webpack生成的模块id,某种道理上来讲,hel经过统一的插件处理与加工并提取构建产物的元数据,相当于是对webpack的模块id做了统一管理,然则怎样管理好并形成pass服务,这个从工程层面怎样处理?
况且联邦模块天生拥有双重身份,即能够是模块消费者,亦能够是模块供给者,这让模块联邦应用之间形成为了天然的网格关系,模块分发效率、安排效率、共享效率都得到了前所未有的提高!
远程模块能够做为微模块(模块级别的微前端),是页面级别的微前端的一种弥补,由于页面级别的微前端,如 qiankun、无界等,它们的粒度太粗了,有时候需要更细粒度的微前端,例如:组件、函数级别的。这种场景,就能够运用远程模块,来实现微模块的效果。 方法微的定义微前端的定义技术实现运用场景MF模块由多个互相独立的模块聚合而成的应用模块本质上是JS代码片段,这种代码片段通常叫作为chunk。因此呢,模块的聚合,实质上是chunk的聚合。是一种技术升级的创造性工作,有必定成本,目的是为了让系统具备更强大的能力。qiankun/wujie/garfish等应用由多个互相独立的应用聚合而成的应用应用本质上是HTML,而在SPA中,HTML又是main.js进行填充的。因此呢,应用的聚合,实质上是main.js的聚合。是一种维持状况的保守性工作,成本极小,目的是为了让系统持有更很久的生命力。模块联邦优良
单体拆分的新处理方法,更小的加载体积,当前子系统已然下载的chunk能够被共享,倘若能够复用,下一个子系统将不会再次下载。
降维打击了 systemjs, 况且能够在运行时拉远程模块和2、三方包,因此,systemjs 应该能够退场了。
mf的远程模块是以webpack打包后的组件形式供给,能够按需在代码任意地区引用,像script标签的引用只适应在全局引用。
运用script的引用,只适应全部模块的共享,例如一个按钮组件,运用script的话就得单独为改组件分配一个共享域名,而运用mf能够在同一个域名内对一个应用的任意模块进行共享。
相比过去, externals 没法多版本共存,dll 没法共享模块,MF 完美处理。
处理了从前用 NPM 公共包方式共享的不方便利。不外换来的是本地起步的巨量的 lib server 。
模块联邦之痛
webpack 5或其他工具带来的模块联邦实现真的完美了吗?
它的确处理了免构建、动态更新、跨项目共享模块的问题,但基于现有的编译时插件化机制去实现,没法规避工具链强绑定,编译时确定才可远程模块消费关系的困难!
MF虽然能做到依赖共享,然则被共享的lib不可做tree-shaken,亦便是说倘若共享了一个lodash,那样全部lodash库都会被打包到shared-chunk中。
MF需升级到webpack5,就项目改导致本大,且webpack为了支持加载remote模块对runtime做了海量改造,在运行时要做的事情亦因此呢陡然增多,可能会对咱们页面的运行时性能导致消极影响。
因此呢倘若要运用mf,就必须对当前的构建工具进行升级,并把现有应用可共享的模块进行提炼,工作量比很强
运行时共享亦是一把双刃剑,怎样去做版本掌控以及掌控共享模块的影响是需要去思虑的问题
针对运用react、vue这一类研发框架的应用,运用mf进行模块共享时还需思虑框架的版本,倘若是应用处在区别的大版本,那样就有可能引起运行上下文的版本不一致,这亦是将应用接入微前端的难点之一。
你需要运用模块联邦这么技术,需要做的前置要求有多重,需要升级全部工具链!况且区别工具链之前的联邦模块是互相不通的!模块的流通性绑定在了你选取的工具链上。
EMP
https://github.com/empjs/emp
EMP 经过 module federation 实现依赖共享,使得依赖不会重新重复(依赖变成全局变量,相同依赖只会留下一个),因此体积会相对 qiankun 更小。
跨框架调用实现。qiankun 经过 dom 隔离的方式,使得跨框架实现非常容易,然则不可互相调用,粒度只能渲染在规定的 dom 区域。EMP 实现的跨框架调用粒度到了 function ,况且运用非常方便。
体积方面。qiankun 由于是经过 dom 隔离方式实现,因此依赖共享并不完善,需要依赖于 systemjs,况且共享不方便,引起依赖可能会显现重复,使得显现体积变大。EMP 经过 module federation 实现依赖共享,使得依赖不会重新重复(依赖变成全局变量,相同依赖只会留下一个),因此体积会相对 qiankun 更小。
然则EMP的详细背面原理,暂时无时间去看源码
hel-micro
hel-micro 自叫作是:业内首个以sdk的方式支持模块联邦技术的方法,它脱离了工具链的枷锁,回归到js语言本身,接入快速、简单、灵活,极重的降低了模块联邦技术的接入门槛,让区别工具链间的联邦模块能够互认互通,加强了模块的流通性.
sdk化后,任何技术栈、任何工具链均可无损、无痛接入模块联邦技术。
运行时的模块消费关系
从工具链回归到js语言本身,寓意着模块消费关系从编译时提高到运行时,将极重加强动态载入远程模块的灵活性,为更繁杂的业务赋能。
对比依赖工具插件实现的模块联邦,hel-micro从语言层面的实现将对其他模块联邦实现导致降维打击。
hel-micro 优良如下:
基于 sdk 的远程加载能力,咱们能够搭配公共cdn安排远程模块(sdk默认指向unp公斤),用户亦能够容易定制自己的模块管控平台,而后重置sdk的请求模块元数据接口就可。
基于核心层供给的远程加载能力,咱们规划了更加多的上层框架远程加载适配器,例如 远程web component组件,远程angular组件、远程vue组件、远程react组件(已实现为hel-micro-react,供给钩子函数加载远程react组件)等。
hel-micro实现原理
一般咱们都会在头文件运用import关键字静态导入其他模块,但其实import能够做为函数调用,异步的导入一个模块,并返回一个promise对象 const mod = await import(./some-mod);因此咱们能够经过微调模块的加载次序,来达到为一个模块被其他模块静态导入之前能够为它注入新代码的效果
而这个异步import带来的提前注入效果作为了hel-micro为模块代理对象注入远程运行时代码的关键实现点,让hel-micro能够位用户供给懒加载和预加载两种加载方式。
上图里两个核心接口:libReady接口负责暴露模块,preFetchLib接口负责拉取模块,经过调用接口的行径让每一个模块都表现为供给方或消费者。运行时依赖分析
当调用 helMicro.preFetchLib 时,先拉取元数据,从元数据中获取到入口脚本的 url,而后拉取远程模块入口并执行,最后 helMicro.preFetchLib 将模块返回,代码中就能够直接运用了。
import 代理模块,实质上是从远程模块的缓存中读取模块。因此呢,必须要等待helMicro.preFetchLib拉取完成后,import 的代理模块才可够获取到远程模块
hel 的默认拉取元数据的方式,是按照远程模块名叫作,到 unp公斤 CDN 对应的 npm 包下,获取元数据 meta_data.json 文件。这个拉取元数据的过程亦能够研发者自定义。
hel-micro经过内部守护的事件总线、模块池、样式池、元数据池四个数据结构,让有多级依赖层次的远程模块得以有效并安全有序的加载。
其中模块池能保准模块不被重复加载并被上层各方调用者重复运用。
元数据-模块的灵魂模块的实质是构建产物文件的集合,hel-micro经过供给构建时的插件,收集好产物的网络路径并按sdk规定的协议存储起来,得以后续能够在网络让sdk能够下载并执行所有的远程模块。
双构建机制hel-micro运用rollup打包本地可静态导入的代理文件,运用webpack打包远程注入的实质运行代码,来达成能够本地静态导入node_modules里的代理模块对象得到完整的类型提示,让用户能得到像运用本地模块同样地运用远程模块的极致研发体验
远程模块发布 CDN,在浏览器运行时,调用helMicro.preFetchLib真正拉取代码
代理模块用于研发时的类型提示,上传到 npm。研发时安装并运用该 npm 包,能够得到 TS 类型提示
元数据是一份 json 配置名单,是在远程模块构建完成后,从构架产物中提取生成的。它记录了远程模块的名叫作、入口脚本路径等信息
内定了4个目录hel_dist,hel_proxy,hel_proxy_es,hel_bundle来承载区别的产物,供package.json配置区别的入口。
其中hel_proxy,hel_proxy_es目录下的文件是便是咱们说到的模块代理对象的入口文件,咱们能够看到该文件近乎一个空壳,因此它对模块运用方的打包体积体积影响几乎能够省略不计。
参考文案:
hel-micro 模块联邦新革命 https://juejin.cn/post/7138792768234586148
腾讯开源的 hel 供给了加载远程模块的能力,谈谈它的实现原理 https://zhuanlan.zhihu.com/p/591621582
关于module Federation的思考 https://geocld.github.io/2021/09/15/module-federation/
转载本站文案《微前端学习笔记(4):从微前端到微模块之EMP与hel-micro方法探索》, 请注明出处:https://www.zhoulujun.cn/html/webfront/engineer/Architecture/9063.html
|