手动远程组件
因为一些交付场景, 最近遇到了2个项目需要使用远程组件.
第一个在疫情居家期间, 使用了module federation实现了一下.
最近的项目尝试了手动加载远程组件, 所以产生了一些对比.
对比的方式是mf和手动.
我会从使用方式, 原理比较, 和各方面综合比较来进行对比.
使用方式
mf
mf的使用方式只需要照着webpack文档操作就行了, 分为主应用和子应用, 子应用比较简单先说
remote
在ModuleFederationPlugin
插件里配置:
- 子应用名字
- 输出的文件名
- 文件入口
- 共享模块
于是webpack打包结果就会多出一个作为远程组件的文件.
master
在ModuleFederationPlugin
插件里配置:
- 远程组件的url和名字
- 共享模块
然后配置ExternalTemplateRemotesPlugin
, 并把应用相关入口改成dynamic import.
使用的时候mf和手动都使用了React.Suspense和React.lazy, mf使用的时候lazy里dynamic import设置好的共享模块名字就可以了.
手动
remote
在webpack配置里增加一个entry指向组件, 并设置output.library.
output.library我尝试过2种设置, umd和window, 都可以正常运行, 打包体积也基本一致(umd会稍微多一点), window的缺点是需要设置name, 让人有些不舒服. (即使可以随便写, 但在使用组件的时候得写额外的逻辑, 想名字也比较花时间)
master
主应用只要做一件事: 手动请求remote组件资源并解析. 然后作为promise的结果返回给lazy方法.
对应着umd打包结果方式是: 准备module,
exports, 和一个对应着远程组件externals的
require()`方法. 然后eval资源, 远程组件就在module.exports里了. 代码片段:
1 | .then((res) => { |
对应window打包结果只需要准备1个变量, 名字随意, 把共享模块放上, 并留一个目标模块的placeholder键, 然后替换资源的window.
成自己的变量, eval变量后, 就得到了模块.
如果觉得麻烦的话, eval以后直接取window.xxx
就行了, 也能走通. 流程化是另外一个话题了.
原理比较
mf
我们这里其实指的是webpack的mf, 所以原理会和webpack比较相关. 之前有文章比较详细的讲了, 这里总结下.
- 当主应用引入了子应用, 会通过网络请求获取到子应用的资源.
- 子应用通过
window.compName
把入口暴露给主应用. 但拥有自己独立的运行闭包. - 子应用加载的时候主子应用会共享一个变量(webpack__.s), 变量里存着需要被共享的模块, 并指向子包的资源. (比如使用子包的react和react-dom)
- 主/子应用配置过的模块都会去共享变量(webpack__.s)里取.
手动
手动加载就简明很多. 主应引用子应用时, 通过网络请求获取子应用的资源, 并根据子应用打包方式最终获取react组件. (其实就是个js方法)
在加载子应用的时候, 通过中间变量将主应用的模块直接传给子应用, 以达到共享模块的目的.
总结
经过了比较以后, 发现这两个方案不可以比较.
因为mf是一套完整的解决方案, 而手动加载只是简单的poc.
但和所有框架的对比一样, 功能完备就会有大多场景都不需要的功能, 我的看法是, 如果场景确定切重复, 推荐手动加载远程组件.
简单的在几个场景下比较一下:
配置复杂度.
相比手动加载只需要把子应用externals的包都注入, mf的配置就比较复杂, 需要配置子应用名字也是一个不舒服的地方.
代码复杂度.
手动加载只有加载的时候有特殊的代码, 抽象一下调用会更简单.
而mf会要求远程组件入口前要dynamic import, 并且引入远程组件的名字也要和配置中的一样.
打包体积.
最明显的是, mf的包必须把依赖都打到包里, 而手动打可以设置externals.
开发体验.
mf在开发的时候要将主应用配置子应用的地址是localhost, 再用monorepo工具同时起2个应用.
手动加载的情况, 开发时主应用直接引用子应用, 但最后要改成加载远程组件的方法.
或者子应用单独作为组件开发, 写个模拟入口.
聊聊mf复杂的原因和手动加载的更大灵活性
其实上面几个mf复杂的原因基本来自于对共享模块的处理, 而我们的场景固定在react组件, 整个应用里不会有多个react版本, 所以就可以少处理很多事.
当然, 有一些地方手动加载比mf更复杂的, 但根据我们自己的业务来开发工具和流程, 手动加载的可扩展性更强, 天花板更高.
(本文完)
如果你觉得本文对你有帮助, 你可以请我喝一杯咖啡
本文遵循cc协议
你可以在注明出处和非商用的前提下任意复制及演绎