概述
前端的工程化已经持续了很长时间,从最开始的手动更新和维护,之后以文件为单位的自动化工具的产生,在开发和部署的过程中进行一系列的操作,最终组成一个较大的 SPA 或者 MPA。随着业务的发展,网页应用越来越多,以文件为单位进行构建则难以维护与复用。webpack5 引入了一个重要的特性 module federation
,目的是解决多业务线,多工程下的模块复用问题。
使用方法
关于module federation
的用法,官方给出了很详细的示例,我们以automatic-vendor-sharing为例简单来看一下是如何使用的:
线上 demo
app1
先看一下 app1 的 webpack 关键配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| new ModuleFederationPlugin({ name: 'app1', filename: 'remoteEntry.js', remotes: { app2: 'app2@http://localhost:3002/remoteEntry.js', }, exposes: { './Button': './src/Button', }, shared: { ...deps, react: { singleton: true, }, 'react-dom': { singleton: true, }, }, }),
|
这里的关键信息是ModuleFederationPlugin
中声明了remotes,然后我们就可以使用了,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import LocalButton from './Button'; import React from 'react';
const RemoteButton = React.lazy(() => import('app2/Button'));
const App = () => ( <div> <h1>Bi-Directional</h1> <h2>App 1</h2> <LocalButton /> <React.Suspense fallback="Loading Button"> <RemoteButton /> </React.Suspense> </div> );
export default App;
|
app2
我们回到 app1 再看一下 app1 的 webpack 配置,注意到 app1 配置了name,filename,以及exposes等信息,在开发和部署时会生成对应的文件,供其它 app 使用,我们来看一下 app2 的 webpack 关键配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| new ModuleFederationPlugin({ name: 'app2', filename: 'remoteEntry.js', remotes: { app1: 'app1@http://localhost:3001/remoteEntry.js', }, exposes: { './Button': './src/Button', }, shared: { ...deps, react: { singleton: true, }, 'react-dom': { singleton: true, }, }, }),
|
app2 中也调用了 app1 的组件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import LocalButton from './Button'; import React from 'react';
const RemoteButton = React.lazy(() => import('app1/Button'));
const App = () => ( <div> <h1>Bi-Directional</h1> <h2>App 2</h2> <LocalButton /> <React.Suspense fallback="Loading Button"> <RemoteButton /> </React.Suspense> </div> );
export default App;
|
如上示例所示,两个应用相互调用对方暴露出来的模块,那么扩展到多个应用也同样合适,这样就可以较好的解决模块复用问题