#webpack
Review
- 2023-03-02 06:15
一、Introduction #
Module Federation 建立在“微服务”的理念之上,允许创建可以独立部署和管理的真正 ==模块化== 的应用程序。更容易维护和修改。
多个独立的 构建 可以组成一个应用程序,这些独立的构建之间不应该存在依赖关系,因此可以单独开发和部署它们。这是模块联邦(Module Federation)可以实现的功能。很像微前端,但不仅如此。
适用于团队大,页面数量多,需要共同开发维护的场景。
Features #
- 开源,无维护成本,易于扩展
- 促进代码复用
- 基于Webpack插件机制,学习成本低、配置快速
- 不需要对每个项目进行重新架构
- 在构建时处理,而不是运行时
- 与Web框架独立
- 不需要处理路由问题
- Shell和Micro Apps是松耦合的
- 可以更轻松的独立测试和调试每个组件
基本概念 #
- webpack构建:一个独立项目通过webpack打包编译而产生资源包。
- remote:一个暴露模块供其他
webpakc构建消费的webpack构建。 - host:一个消费其他
remote模块的webpack构建。
二、实践 #
更多示例参考
module-fereration-examples
webpack@^5 支持的特性
mkdir shell
cd shell
yarn add webpack webpack-cli webpack-dev-server html-webpack-plugin css-loader style-loader babel-loader -E -D一共有三个微应用:lib-app、component-app、main-app,角色分别是:
lib-appas remote,暴露了两个模块react和react-domcomponent-appas remote and host,依赖lib-app,暴露了一些组件供main-app消费main-appas host,依赖lib-app和component-app
lib-app configuration
//webpack.config.js
const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
entry: './src/index',
mode: 'development',
devServer: {
port: 3002,
},
output: {
publicPath: 'auto',
clean: true,
},
module: {},
plugins: [
new ModuleFederationPlugin({
name: 'libs',
filename: 'remoteEntry.js',
exposes: {
'./react': 'react',
'./react-dom': 'react-dom',
},
}),
],
};// component webpack.config.js
new ModuleFederationPlugin({
name: 'remote',
filename: 'remoteEntry.js',
remotes: {
'libs': 'libs@http://localhost:3002/remoteEntry.js'
},
exposes: {
'./Button': './src/Button'
},
}),// shell webpack.config.js
new ModuleFederationPlugin({
name: 'host',
remotes: {
'remote': 'remote@http://localhost:3001/remoteEntry.js',
'libs': 'libs@http://localhost:3002/remoteEntry.js',
},
}),name应用程序的名称,用来跟其他App通信filename是入口文件,其他应用可以访问,如libs@http://localhost:3002/remoteEntry.js访问该应用程序exposes允许从当前应用程序共享组件、页面、或整个应用程序到另一个应用程序。每一个公开的内容都是作为单独的构建创建的。每个构建都是以文件的MD5哈希命名,不必担心缓存。shared指定当前应用程序将对其他应用程序共享哪些依赖项。remotes确定从哪些应用程序接收组件、页面或应用程序本身。
每个应用程序都可以指定 exposes 和 remotes 。
src/bootstrap.js
import React from 'libs/react';
import ReactDom from 'libs/react-dom';
const Button = React.lazy(() => import('remote/Button'));
function App() {
return <div>
<div style={{ height: 100 , backgroundColor: '#005599', textAlign: 'center'}}>test</div>
<React.Suspense fallback="Loading Button">
<Button />
</React.Suspense>
</div>
}
ReactDom.render(<App />, document.getElementById('root'))由于需要等待基础模块加载完毕,所以需要配置懒加载入口bootstrap.js 。
src/index.js
import('./bootstrap');lib执行 yarn build
dist
├── main.js // 项目入口文件
├── remoteEntry.js // 远程入口文件
├── remoteEntry.js.map
├── vendors-node_modules_react-dom_index_js.js // 暴露的模块
├── vendors-node_modules_react-dom_index_js.js.map
├── vendors-node_modules_react_index_js.js // 暴露的模块
└── vendors-node_modules_react_index_js.js.mapmodule federation策略
- 模块尽可能小和独立
- 模块尽可能松耦合