模块联邦是webpack5
的一个新特性,在运行时允许使用其他独立构建模块。通过模块联邦可以解决微前端依赖问题,对比npm库具有实时性的优势。
app1
const { defineConfig } = require("@vue/cli-service");
const { ModuleFederationPlugin } = require("webpack").container;
module.exports = defineConfig({
transpileDependencies: true,
devServer: {
port: 8080,
},
chainWebpack: (config) => {
config.plugin("module-feaderation-plugin").use(ModuleFederationPlugin, [
{
// 指定输出的容器名称
name: "app1",
// 引用远程的 expose 模块
remotes: {
app2: "app2@http://localhost:8082/remoteEntry.js",
},
shared: {
vue: {
singleton: true,
},
},
},
]);
},
});
app2
const { defineConfig } = require("@vue/cli-service");
const { ModuleFederationPlugin } = require("webpack").container;
module.exports = defineConfig({
transpileDependencies: true,
publicPath: "http://localhost:8082/",
devServer: {
port: "8082",
// 配置允许跨域,解决热更新报错
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Method": "GET,POST,PUT,OPTIONS",
},
},
chainWebpack: (config) => {
config
.plugin("module-feaderation-plugin")
.use(ModuleFederationPlugin, [
{
// 指定导出的容器名称
name: "app2",
// 打包生成的文件名称
filename: "remoteEntry.js",
// 导出对应的模块
exposes: {
"./HelloWorld": "./src/components/HelloWorld.vue",
"./utils": "./src/utils/index.js",
},
shared: {
vue: {
singleton: true,
},
},
},
])
.end()
.optimization.delete("splitChunks");
},
});
在app1项目中使用
现在创建bootstrap.js文件,把main.js的内容复制到bootstrap.js
import { createApp } from "vue";
import App from "./App.vue";
createApp(App).mount("#app");
然后main.js异步引入bootstrap.js文件
import("./bootstrap");
因为是异步组件库,所以要通过import()来引入。
<template>
<HelloWorld />
{{ utilsSum }}
</template>
<script setup>
import { defineAsyncComponent, ref } from "vue";
const HelloWorld = defineAsyncComponent(() => import("app2/HelloWorld"));
const utilsSum = ref(0);
import("app2/utils").then((utils) => {
utilsSum.value = utils.sum(1, 4);
});
</script>