手动远程组件
因为一些交付场景, 最近遇到了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更复杂的, 但根据我们自己的业务来开发工具和流程, 手动加载的可扩展性更强, 天花板更高.
(本文完)
如果你可以 点击这个链接打赏我5毛来鼓励我, 非常感谢.
本文遵循 cc协议
你可以在注明出处和非商用的前提下任意复制及演绎