使用Vue Vite和模块联合会建造微观前端体系结构

使用Vue Vite和模块联合会建造微观前端体系结构
最新回答
苝汸姠涼遖汸煖

2022-12-29 17:05:36

基于Vue 3、Vite和Module Federation的微前端架构可通过动态路由和独立Vue实例实现模块化开发,核心步骤包括配置路由清单、创建加载器组件、利用Module Federation动态加载微前端(MFEs),并确保各MFE拥有独立Vue实例以避免依赖冲突。

一、架构核心原理
  • 模块化拆分:将整体前端拆分为主应用和多个微前端(MFEs),每个MFE独立开发、部署和维护。
  • 动态加载:主应用通过路由清单动态注册MFE路由,运行时按需加载远程MFE,减少初始加载时间。
  • 独立Vue实例:每个MFE拥有独立的Vue实例,主应用与MFE、MFE之间完全隔离,避免依赖冲突。
  • 路由管理:所有路由指向主应用的loader.vue组件,由其负责安装/卸载MFE,确保单例运行。
二、具体实现步骤1. 项目初始化与依赖安装
  • 克隆示例仓库并安装依赖:git clone
    https://github.com/lmlong-huynh/micro-frontend-sample.gitcd
    micro-frontend-samplenpm install
  • 启动所有服务(主应用+MFEs)或单独启动:npm run dev # 启动全部# 或单独启动cd packages/host && npm run devcd packages/app-1 && npm run devcd packages/app-2 && npm run dev
2. 配置路由清单
  • 在主应用中定义routeManifest.js,声明路由与远程MFE的映射关系:export const routeManifest = [ { route: { path: '/app-1', name: 'app1', meta: { requiresAuth: false }, }, remote: { module: 'app1/app' } // 指定从哪个MFE加载组件 }, { route: { path: '/app-2', name: 'app2', meta: { requiresAuth: false }, }, remote: { module: 'app2/app' } }];
  • 在路由器文件(router/index.js)中动态生成路由,所有路由指向loader.vue:import { createRouter, createWebHistory } from 'vue-router';import routeManifest from '../routeManifest';const getRoutes = () => { return routeManifest.map((mfe) => ({ path: mfe.route.path, name: mfe.route.name, meta: mfe.route.meta, component: () => import('@/components/loader.vue'), // 统一指向加载器 }));};const routes = getRoutes();const router = createRouter({ history: createWebHistory(), routes,});export default router;
3. 创建加载器组件(loader.vue)
  • 功能:根据当前路由动态加载远程MFE,并管理其生命周期(安装/卸载)。
  • 关键逻辑

    监听路由变化,通过routeManifest确定目标MFE。

    使用Module Federation动态加载远程组件。

    维护currentModule状态,卸载旧MFE后再加载新MFE,确保单例运行。

  • 代码示例:<template> <div ref="containerRef"></div></template><script>import { ref, onMounted, watch } from 'vue';import { useRoute } from 'vue-router';import { useModuleFederation } from '@/plugins/federationPlugin';import routeManifest from '../routeManifest';export default { setup() { const route = useRoute(); const moduleFederation = useModuleFederation(); const containerRef = ref(null); const currentModule = ref(null); const loadRemoteModule = async () => { const targetRoute = routeManifest.find(m => m.route.path === route.path); if (!targetRoute) return; // 卸载旧模块 if (currentModule.value) { currentModule.value.unmount(); } // 动态加载新模块 const module = await moduleFederation.load(targetRoute.remote.module); if (module) { currentModule.value = module; module.mount(containerRef.value); // 挂载到DOM } }; // 路由变化时重新加载 watch(() => route.path, loadRemoteModule, { immediate: true }); return { containerRef }; },};</script>
4. 配置Module Federation
  • 主应用配置(vite.config.js):import { defineConfig } from 'vite';import vue from '@vitejs/plugin-vue';import federation from '@originjs/vite-plugin-federation';export default defineConfig({ plugins: [ vue(), federation({ remotes: { app1: '
    http://localhost:5001/assets/remoteEntry.js'
    , // MFE1的入口地址 app2: '
    http://localhost:5002/assets/remoteEntry.js'
    , // MFE2的入口地址 }, }), ],});
  • MFE配置:需暴露组件供主应用调用(示例为app1/vite.config.js):federation({ name: 'app1', filename: 'remoteEntry.js', exposes: { './app': './src/main.js', // 暴露的组件入口 },}),
三、关键优势
  • 性能优化:按需加载MFE,减少初始资源体积。
  • 隔离性:独立Vue实例和依赖管理,避免版本冲突。
  • 可扩展性:新增MFE无需修改主应用代码,仅需更新路由清单。
  • 开发效率:团队可并行开发不同MFE,独立部署迭代。
四、扩展场景
  • 嵌套路由:可在MFE内部实现二级路由,需主应用传递路由上下文。
  • 共享依赖:通过Module Federation的shared配置共享公共库(如Vue、Vue Router)。
  • 状态管理:使用Pinia或Redux的独立实例,或通过主应用统一管理全局状态。

完整实现可参考GitHub仓库,通过实验进一步验证架构的灵活性与稳定性。