模块联邦
- 可使用webpack模块联邦来实现微前端应用
- 远程模块动态加载,将原本单个巨大应用按我们理想的方式拆分成多个体积更小、职责更内聚的小应用形式
- 能够实现独立部署、独立开发(不同应用甚至允许使用不同技术栈)
- 模块联邦目的就是更好的共享代码
依赖于 Webpack 5 内置的 ModuleFederationPlugin 插件
使用
远程模块 remote
配置:
const path = require("path");
const { ModuleFederationPlugin } = require("webpack").container;
module.exports = {
mode: "development",
devtool: false,
entry: path.resolve(__dirname, "./src/main.js"),
output: {
path: path.resolve(__dirname, "./dist"),
// 必须指定产物的完整路径,否则使用方无法正确加载产物资源
publicPath: "http://localhost:8081/dist/",
},
plugins: [
new ModuleFederationPlugin({
// MF 应用名称
name: "app1",
// MF 模块入口,可以理解为该应用的资源清单
filename: "remoteEntry.js",
// 定义该应用导出哪一些模块
exposes: {
"./utils": "./src/utils",
"./foo": "./src/foo",
},
shared: {
lodash: {
requiredVersion: "^4.17.0",
// version: "4.17.20",
singleton: true,
// shareKey: "single",
strictVersion: false,
},
},
}),
],
// 应用资源必须以 http(s) 形式提供服务
// 所以这里需要使用 devServer 提供 http(s) server 能力
devServer: {
port: 8081,
hot: true,
},
};
远程模块的工具函数 utils.js
export const sayHello = () => {
console.log("hello world!");
};
本地模块 host
配置:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { ModuleFederationPlugin } = require("webpack").container;
module.exports = {
mode: "development",
devtool: false,
entry: path.resolve(__dirname, "./src/main.js"),
output: {
path: path.resolve(__dirname, "./dist"),
},
plugins: [
// 模块使用方也依然使用 ModuleFederationPlugin 插件搭建 MF 环境
new ModuleFederationPlugin({
// 使用 remotes 属性声明远程模块列表
remotes: {
// 地址需要指向导出方生成的应用入口文件
RemoteApp: "app1@http://localhost:8081/dist/remoteEntry.js",
},
exposes: {},
shared: { lodash: {} },
}),
new HtmlWebpackPlugin(),
],
devServer: {
port: 8082,
hot: true,
open: true,
},
};
使用远程模块
(async () => {
const { sayHello } = await import("RemoteApp/utils"); // 远程模块
sayHello();
})();