Webpack5新特性之模块联邦
大家好,很高兴又见面了,我是web前端分享,由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!1引言
Webpack5
先说结论:Webpack5模块联邦让Webpack达到了线上Runtime的效果,让代码直接在项目间利用CDN直接共享,不再需要本地安装Npm包、构建再发布了!
我们知道Webpack可以通过DLL或者Externals做代码共享时CommonChunk,但不同应用和项目间这个任务就变得困难了,我们几乎无法在项目之间做到按需热插拔。
模块联邦是Webpack5新内置的一个重要功能,可以让跨应用间真正做到模块共享,所以这篇文章将带你了解什么是模块联邦功能。2概述精读NPM方式共享模块
想象一下正常的共享模块方式,对,就是NPM。
如下图所示,正常的代码共享需要将依赖作为Lib安装到项目,进行Webpack打包构建再上线,如下图:
对于项目Home与Search,需要共享一个模块时,最常见的办法就是将其抽成通用依赖并分别安装在各自项目中。
虽然Monorepo可以一定程度解决重复安装和修改困难的问题,但依然需要走本地编译。UMD方式共享模块
真正Runtime的方式可能是UMD方式共享代码模块,即将模块用WebpackUMD模式打包,并输出到其他项目中。这是非常普遍的模块共享方式:
对于项目Home与Search,直接利用UMD包复用一个模块。但这种技术方案问题也很明显,就是包体积无法达到本地编译时的优化效果,且库之间容易冲突。微前端方式共享模块
微前端:microfrontends(MFE)也是最近比较火的模块共享管理方式,微前端就是要解决多项目并存问题,多项目并存的最大问题就是模块共享,不能有冲突。
由于微前端还要考虑样式冲突、生命周期管理,所以本文只聚焦在资源加载方式上。微前端一般有两种打包方式:子应用独立打包,模块更解耦,但无法抽取公共依赖等。整体应用一起打包,很好解决上面的问题,但打包速度实在是太慢了,不具备水平扩展能力。模块联邦方式
终于提到本文的主角了,作为Webpack5内置核心特性之一的FederatedModule:
从图中可以看到,这个方案是直接将一个应用的包应用于另一个应用,同时具备整体应用一起打包的公共依赖抽取能力。
让应用具备模块化输出能力,其实开辟了一种新的应用形态,即中心应用,这个中心应用用于在线动态分发Runtime子模块,并不直接提供给用户使用:
对微前端而言,这张图就是一个完美的主应用,因为所有子应用都可以利用Runtime方式复用主应用的Npm包和模块,更好的集成到主应用中。
模块联邦的使用方式如下:constHtmlWebpackPluginrequire(htmlwebpackplugin);constModuleFederationPluginrequire(webpacklibcontainerModuleFederationPlugin);module。exports{otherwebpackconfigs。。。plugins:〔newModuleFederationPlugin({name:apponeremote,remotes:{apptwo:apptworemote,appthree:appthreeremote},exposes:{AppContainer:。srcApp},shared:〔react,reactdom,reactrouterdom〕}),newHtmlWebpackPlugin({template:。publicindex。html,chunks:〔main〕})〕};
模块联邦本身是一个普通的Webpack插件ModuleFederationPlugin,插件有几个重要参数:name当前应用名称,需要全局唯一。remotes可以将其他项目的name映射到当前项目中。exposes表示导出的模块,只有在此申明的模块才可以作为远程依赖被使用。shared是非常重要的参数,指定了这个参数,可以让远程加载的模块对应依赖改为使用本地项目的React或ReactDOM。
比如设置了remotes:{apptwo:apptworemote},在代码中就可以直接利用以下方式直接从对方应用调用模块:import{Search}fromapptwoSearch;
这个apptwoSearch来自于apptwo的配置:apptwo的webpack配置exportdefault{plugins:〔newModuleFederationPlugin({name:apptwo,library:{type:var,name:apptwo},filename:remoteEntry。js,exposes:{Search:。srcSearch},shared:〔react,reactdom〕})〕};
正是因为Search在exposes被导出,我们因此可以使用〔name〕〔exposesname〕这个模块,这个模块对于被引用应用来说是一个本地模块。3总结
模块联邦为更大型的前端应用提供了开箱解决方案,并已经作为Webpack5官方模块内置,可以说是继Externals后最终的运行时代码复用解决方案。
另外Webpack5还内置了大量编译时缓存功能,可以看到,无论是性能还是多项目组织,Webpack5都在尝试给出自己的最佳思路,期待Webpack5正式发布,前端工程化会迈向一个新的阶段。参考资料
原文链接:https:github。comascodersweeklyblobmasterE5898DE6B2BFE68A80E69CAF144。E7B2BEE8AFBBE3808AWebpack520E696B0E789B9E680A72020E6A8A1E59D97E88194E982A6E3808B。md