微前端架构通过将大型单体前端应用拆分为多个独立部署的子应用,解决了前端工程化中的团队协作和持续交付效率问题。Webpack 5引入的Module Federation(模块联邦)原生支持跨应用共享模块,无需引入qiankun等框架即可实现微前端。对于Vue3生态和React框架混用的技术栈,Module Federation提供了一套统一的跨应用组件共享方案。
Module Federation核心概念与Host端配置
Module Federation定义了两个角色:Host(容器应用)消费远程模块,Remote(远程应用)暴露模块。每个应用可以同时扮演两种角色。核心配置项包括name(应用唯一标识)、remotes(依赖的远程应用)、exposes(暴露的模块)和shared(共享依赖)。
// webpack.config.js (Host应用)
const { ModuleFederationPlugin } = require("webpack").container;
const deps = require("./package.json").dependencies;
module.exports = {
output: {
publicPath: "http://localhost:3000/",
},
plugins: [
new ModuleFederationPlugin({
name: "host",
remotes: {
userApp: "userApp@http://localhost:3001/remoteEntry.js",
orderApp: "orderApp@http://localhost:3002/remoteEntry.js",
},
shared: {
vue: { singleton: true, requiredVersion: deps.vue },
"vue-router": { singleton: true, requiredVersion: deps["vue-router"] },
pinia: { singleton: true, requiredVersion: deps.pinia },
},
}),
],
};
shared配置中的singleton: true确保Vue实例全局唯一,避免多个子应用各自加载Vue后组件通信失败。requiredVersion指定版本要求,版本不兼容时WebpackPlugin会抛出警告。publicPath必须配置为绝对路径,因为远程应用加载的异步chunk需要知道资源基础路径。如果是HTTPS域名部署,publicPath也要对应切换。
Remote端模块暴露与组件共享
子应用通过exposes暴露组件、路由配置或工具函数给Host消费。同时通过shared声明与Host共享的依赖,避免重复加载。
// webpack.config.js (userApp远程应用)
const { ModuleFederationPlugin } = require("webpack").container;
const deps = require("./package.json").dependencies;
module.exports = {
output: {
publicPath: "http://localhost:3001/",
},
plugins: [
new ModuleFederationPlugin({
name: "userApp",
filename: "remoteEntry.js",
exposes: {
"./UserList": "./src/components/UserList.vue",
"./UserRouter": "./src/router/userRouter.js",
"./useUserStore": "./src/stores/userStore.js",
"./UserTypes": "./src/types/user.ts",
},
shared: {
vue: { singleton: true, requiredVersion: deps.vue },
"vue-router": { singleton: true, requiredVersion: deps["vue-router"] },
pinia: { singleton: true, requiredVersion: deps.pinia },
},
}),
],
};
exposes的key是消费时使用的模块路径(userApp/UserList),value是子应用内的实际文件路径。暴露路由模块可以实现子应用自治路由注入Host路由表。暴露Pinia store使得Host和子应用共享同一状态实例。filename指定远程入口文件名,通常命名为remoteEntry.js,Host通过该文件发现子应用暴露的所有模块。
跨应用路由配置与动态加载
微前端路由有两种方案:路由集中式(Host管理所有路由)和路由分布式(子应用注册各自路由)。推荐分布式路由方案,子应用通过暴露路由配置数组由Host动态合并:
// userApp: src/router/userRouter.js
export default [
{
path: "/users",
name: "UserList",
component: () => import("userApp/UserList"),
meta: { title: "用户管理", icon: "user" }
},
{
path: "/users/:id",
name: "UserDetail",
component: () => import("userApp/UserDetail"),
meta: { title: "用户详情", hidden: true }
}
];
// Host: src/router/index.js
import { createRouter, createWebHistory } from "vue-router";
const routes = [
{
path: "/",
component: () => import("@/views/Layout.vue"),
children: [
{ path: "", redirect: "/dashboard" },
{
path: "dashboard",
name: "Dashboard",
component: () => import("@/views/Dashboard.vue")
}
]
}
];
// 动态加载子应用路由
async function loadRemoteRoutes() {
const userRouter = (await import("userApp/UserRouter")).default;
const orderRouter = (await import("orderApp/OrderRouter")).default;
routes[0].children.push(...userRouter, ...orderRouter);
}
const router = createRouter({
history: createWebHistory(),
routes,
});
export { router, loadRemoteRoutes };
loadRemoteRoutes函数在Host应用初始化时调用,通过import()动态加载远程路由模块。子应用路由以子路由形式挂载到Layout下方,共享侧边栏导航和顶栏。需要处理路由404兜底:将catch-all路由放在动态路由注册之后,否则子路由会被catch-all提前拦截。路由守卫中需要判断远程模块是否已加载,避免在模块未就绪时跳转到子应用页面导致白屏。
共享依赖版本冲突处理与降级策略
多个子应用依赖不同版本的同一库时,shared配置需要开启singleton降级或allowVersionMismatch。降级策略确保功能可用但可能存在兼容性风险:
// 允许版本不匹配(谨慎使用)
shared: {
vue: {
singleton: true,
requiredVersion: "^3.3.0",
strictVersion: false,
// strictVersion为false时,版本不匹配仅警告不报错
},
axios: {
singleton: false, // 允许多版本共存
requiredVersion: deps.axios,
}
}
// 类型声明共享(TypeScript项目)
// types.d.ts
declare module "userApp/UserList" {
import { DefineComponent } from "vue";
const component: DefineComponent<{}, {}, any>;
export default component;
}
对于无法共享的复杂依赖(如UI组件库的不同大版本),使用singleton: false让各自加载独立实例。TypeScript项目需要为远程模块声明类型文件,否则编译期类型检查报错。生产环境需配置runtime error boundary捕获远程模块加载失败的异常,降级展示本地兜底组件或错误提示。remoteEntry.js文件需配置CDN缓存策略,同时通过版本号或hash值实现缓存失效。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/wei-qian-duan-jia-gou-shi-zhan-webpackmodulefederation-kua/