开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 10 天,点击查看活动详情
MFSU能做什么:
Module Federation Speed Up, 基于 webpack
- 解决我们既要 webpack 的功能和生态,又要 Vite 的速度的问题
- 快是他的主要特点,二次启动远远快于原生编译
- 可上生产,除了本地快,CI & CD 流程也快。
MFSU 的原理
来自云谦大佬对MFSU的解释
项目 源码 会走到 babel 插件,插件会做两件事,1、修改源码,从 remote 获取资源 2、收集依赖到依赖图谱;然后依赖图谱会通知 dep builder 做依赖的预编译,这里可以选 esbuild 或 webpack,产出的格式都是 module federation;最后修改后的源码会加载这份预编译后的依赖,形成 BI 环。
嗯,看似很直接了当,利用webpack的module federation,将依赖存在本地,第二次加载时作为host应用直接加载remote文件,仿佛产品在做介绍系统的时候说: 我们要做个系统,满足门店收银的功能,可以收钱,打账单,存储信息。真正落地的时候发现需要涉及到入库、出库、报表、店仓、商品管理、供应链、打印、活动,实践起来发现有很多环节要关注,很多方案要讨论。那么,下面来介绍MFSU是如何站在module federation的肩膀更上一层楼的
MFSU站在了谁的肩膀上
不多提了
一个工具链,主要用于将采用 ECMAScript 2015+ 语法编写的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中
Webpack 5的新功能,也是MFSU的核心,让不同项目的模块可以通过远程提供给其它项目使用,下面介绍的内容与它有密不可分的联系,建议大家先了解了解,中文介绍 看这里
UMI是插件化的企业级前端应用框架,封装了基于它的插件开发脚手架,在开发插件时暴露了编译生命周期方法
构建流程
-
概览
以下是MFSU插件构建流程
从第一节描述可知MFSU本质上是依赖的临时存储做构建提速的,在其内部维护着两个核心类,它们分别是DepInfo与DepBuilder,在onStart中会初始化
DepInfo负责基于babel做依赖信息的获取,DepBuilder负责基于MF Remote与DepInfo做依赖的构建
同时结合webpack编译周期通过MF Host进行依赖消费,形成整个编译提速的闭环
为便于理解,本文不会单独详细介绍depInfo与depBuilder的内部功能,而是从编译顺序角度解释他们是如何助力提速的。
-
依赖获取
在插件初始化时,会寻找当前是否存在依赖映射文件(即项目代码用到的依赖与版本的映射JSON),若存在,则读取文件中的内容存在内存中,避免后续用时频繁读取文件造成性能损耗,首次启动是不存在的。
-
依赖匹配
既然依赖信息首次没有,插件需要想办法去获取,UMI本身集成了webpack,因此,插件可以在babel做AST转换时获取业务代码引入的依赖名。拿到依赖名后,会验证本地node modules是否存在该依赖包,若存在则找到依赖包对应的插件版本(通过package.json获取),然后写入依赖映射文件。最终生成如上图所示依赖信息
-
建立Module Federation消费规则
同时插件本身会监听modifyBundleConfig事件, 当整个AST树遍历完成后,会使用webpack的Module Federation功能建立远程依赖规则,指定依赖数据获取入口文件,若此时本地存在临时依赖包,则会加速构建速度,做到热启动
-
依赖构建
构建触发节点
UMI本身会在构建完成时暴露onDevCompileDone hooks,此时DepBuilder就开始发挥作用了,此时大家会有疑问了,为什么DepBuilder要选择在构建完成后运行,我们从构建链路上理一下,如果是首次构建,用户是需要走一遍不依赖MF的编译全流程的,如果获取到构建信息后再塞入MF构建,用户等待时间会变长,而这个时间是完全没必要等的,因为它并不牵扯页面构建的主流程。
构建触发条件
插件会比较上次构建依赖信息与当前AST解析依赖信息是否有差异,只要存在差异就会触发构建流程,同时插件支持force build以避免版本差异保存,缓存文件缺失等非预期的问题
构建流程
首先build方法会根据依赖映射,生成导入语法文件,然后基于Module Federation Remote端进行构建,并指定输出文件,与上一节提到的Module Federation Host的引入入口文件相对应,同时更改依赖构建包chunk名以及输出路径,最终在.mfsu下会构建出依赖的临时文件,并且生成remoteEntry文件,它的作用就是连接缓存依赖文件以供二次构建时使用
自此依赖临时文件生成,二次构建是依赖直接基于MF HOST构建,形成闭环
-
MFSU在module federation的基础上做了什么?
MF提供的功能是编译时可以直接引入远程已经打包好的依赖数据,自然很多人都会想到这可以用于打包提速,但里面做的事情还有很多
- 基于AST获取依赖信息
- 依赖版本检测
- commonjs包剔除
- 构建优化。不影响主流程
- 开发过程中,不过度频繁进行写入操作
- 构建进度提示
- ...
从提出方案到实际落地往往需要1-2周的时间,是的,这也许就是mfsu做出来的初衷,也是UMI的初衷,开箱即用。 如果是重复的事情,就交给工具去做好了
当然umi团队也很识趣,插件名就是module Federation Speed Up,精髓还是联邦依赖,不过这确实减少了开发者的很多冗余开发成本,也是目前国内webpack领域最被认可的MF落地方案
参考文章
Webpack5 新功能 Module Federation 用法
有bug?想补充?
感谢大家观看这篇文章,有任何问题或想和我交流,请直接留言,
发现文章有不妥之处,也可指出交流,感谢阅读~