当前位置: 首页 > news >正文

Vite模块联邦(vite-plugin-federation)实现去中心化微前端后台管理系统架构

提示:记录工作中遇到的需求及解决办法

文章目录

  • 前言
    • 依赖版本要求
  • 一、架构设计
    • 1.1 模块联邦基础概念
      • 1.1.1 什么是模块联邦
      • 1.1.2 基本配置示例
    • 1.2 去中心化微前端架构设计
      • 1.2.1 传统微前端 vs 去中心化微前端
    • 1.3 特殊架构设计:menuModule 的角色
      • 1.3.1 为什么需要 menuModule?
      • 1.3.2 menuModule 的特殊定位
  • 二、技术实现
    • 2.1 模块联邦配置详解
      • 2.1.1 关键配置参数解析
    • 2.2 构建时处理
  • 三、动态模块的导入与路由整合
    • 3.1 传统导入方式的局限
    • 3.2 动态模块实现
    • 3.3 路由表的共享与整合
    • 3.4 路由合并核心逻辑
  • 四、状态管理与模块通信
    • 4.1 基于缓存的状态管理
    • 4.2 缓存模块的核心特性
    • 4.3 模块间通信方式
  • 五、项目结构与配置
    • 5.1 微前端模块文件架构
    • 5.2 完整的 vite.config.ts 示例
    • 5.3 部署与注册机制
  • 六、总结


前言

在现代大型前端项目开发中,多团队协作时往往面临代码隔离与集成的挑战。为了解决这一问题,我们需要一种能够让各个微前端模块既能独立开发部署,又能作为完整系统一部分的解决方案。基于 Vite 的模块联邦插件 @originjs/vite-plugin-federation 提供了一种去中心化的微前端架构实现方式,实现了组件、路由的跨应用共享和动态加载。本文将结合实际项目经验,详细介绍如何利用模块联邦技术在 「vue3 生态」中构建去中心化的微前端架构。

依赖版本要求

node: 18.20.5

{"vite": "^6.0.2","@originjs/vite-plugin-federation": "1.4.1",
}

提示:以下是本篇文章正文内容,下面案例可供参考

一、架构设计

1.1 模块联邦基础概念

1.1.1 什么是模块联邦

@originjs/vite-plugin-federation 是 Vite 生态中实现模块联邦功能的插件,它允许多个独立应用在运行时共享模块和代码,无需重复构建或打包依赖。这一特性在去中心化微前端架构中尤为关键。

1.1.2 基本配置示例

一个微前端模块的典型配置如下:

federation({name: "pageAModule",        // 微前端模块名称filename: "pageAEntry.js",  // 入口文件名exposes: {                  // 暴露的模块,此处为路由'./routes': './src/routes/index.ts'},remote: {menuModule: ModuleUrl, // 引入的远程模块}shared: ['vue', 'vue-router', 'pinia']  // 共享依赖
})
// 使用远程模块
import 'menuModule/xxx'

1.2 去中心化微前端架构设计

1.2.1 传统微前端 vs 去中心化微前端

传统微前端架构通常采用 “基座模式”,即一个主应用作为基座控制其他子应用的加载和渲染。而去中心化微前端架构没有明确的主应用,各个子应用可以独立部署、独立运行,同时又能无缝协作。

去中心化微前端架构的主要特点:

  1. 「无中心基座」:没有固定的主应用控制全局状态
  2. 「平等协作」:每个应用都可作为入口,并动态加载其他应用模块
  3. 「路由共享机制」:所有微前端模块共享路由表,实现无缝导航
  4. 「共享运行时」:应用间共享关键依赖和状态
    请添加图片描述
    在这里插入图片描述
    请添加图片描述

1.3 特殊架构设计:menuModule 的角色

虽然我们采用去中心化的微前端架构,但在后台管理系统中,我们仍然需要一个统一的菜单管理模块(menuModule)。来提供系统的 layout 和管理一些公共文件。

1.3.1 为什么需要 menuModule?

  • 「统一的菜单管理」:后台管理系统需要一个统一的菜单体系,确保用户体验的一致性
  • 「权限控制中心」:集中管理各个页面模块的访问权限
  • 「导航状态维护」:统一处理菜单的激活状态、展开状态等
  • 「系统级功能集成」:包含用户信息、全局设置等系统级功能

1.3.2 menuModule 的特殊定位

menuModule 模块需要在所有的页面项目中引入,且所有项目在 vite 的 federation 中都只需引入这一个 menuModule 模块就行。 其他剩余的模块引入方式,在下文有提到。

menuModule 承担以下职责:

  • 提供统一的布局容器(Layout)
  • 管理全局导航菜单
  • 处理用户认证和权限
  • 提供公共组件和工具函数

二、技术实现

2.1 模块联邦配置详解

在实际项目中,每个页面的微前端模块的联邦配置通常包含以下部分:

federation({name: config.projectPrefix + 'Module',      // 微前端模块名称filename: config.projectPrefix + 'Entry.js', // 入口文件名exposes: {'./routes': './src/routes/index.ts',      // 暴露路由配置(关键)},remotes: {// 后台管理系统中需要单独引入菜单模块menuModule: ModuleUrl,},shared: ['vue', 'vue-router', 'pinia', 'dayjs', 'axios', 'sass', 'element-plus'], // 共享依赖
})

2.1.1 关键配置参数解析

  1. 「name」:微前端模块的唯一标识符,其他模块通过此名称引用
  2. 「filename」:构建后的入口文件名,通常以 Entry.js 结尾
  3. 「exposes」:暴露的模块,主要是路由配置,这是实现去中心化的关键
  4. 「remotes」:需要引用的其他微前端模块,指定模块的 URL 或加载方式
  5. 「shared」:所有微前端模块间共享的依赖,确保单一实例,避免重复加载

2.2 构建时处理

在构建微前端模块时,vite-plugin-federation 会进行以下处理:

  1. 识别 exposes 配置中声明的路由模块
  2. 为每个模块生成独立的构建产物
  3. 创建容器模块,管理模块的导出和依赖关系
  4. 生成远程入口文件,处理模块的加载和解析

三、动态模块的导入与路由整合

3.1 传统导入方式的局限

传统的模块联邦使用方式是预先声明远程模块并直接导入:

// 常规的模块联邦导入方法
import Component from 'remoteModule/Component'

这种方式存在一个重要限制:「无法使用动态字符串拼接模块名」。例如,以下代码在模块联邦中不起作用:

// 这种写法在模块联邦中不支持
const moduleName = 'remoteModule'
import Component from `${moduleName}/Component` // 不支持!

这样就会导致一个问题就是 在去中心化微前端架构中,每个项目模块在开发时并不知道全局系统中到底有多少个联邦模块,也无法预先确定所有模块的名称和地址。为了支持新增模块的灵活扩展,需要一个动态的机制来发现和加载模块。通常,我们会通过一个配置文件(如 registry.json)来集中管理所有联邦模块的注册信息,允许新模块随时加入系统。然而,官方的模块联邦导入方式,它不支持动态拼接模块名称的字符串。

为了解决这一问题,我实现了一个支持动态拼接模块名称的加载函数 getRemoteEntries。通过该函数,我们可以在运行时根据配置文件动态获取模块的 URL 并加载模块,从而实现真正的动态模块发现和集成。这种方式不仅解决了官方导入方式的限制,还为系统的扩展性和灵活性提供了强有力的支持。

3.2 动态模块实现

为解决上述限制,我实现了 getRemoteEntries 函数,通过 @originjs/vite-plugin-federationget API 实现,运行时动态的模块声明和加载:

// src/utils/federation.ts
export const getRemoteEntries = async (name ? : string, moduleName ? : string): Promise < any[] > => {try { // 从注册中心获取所有可用模块的信息    const response = await axios.get(`${baseUrl}/federation/registry.json`)// 定义过滤条件    const filterByName 
http://www.lqws.cn/news/152155.html

相关文章:

  • 《C++初阶之类和对象》【命名空间 + 输入输出 + 缺省参数 + 函数重载】
  • ubuntu系统文件误删(/lib/x86_64-linux-gnu/libc.so.6)修复方案 [成功解决]
  • .Net Framework 4/C# LINQ*
  • 机器学习的数学基础:决策树
  • 双空间知识蒸馏用于大语言模型
  • win32相关(远程线程和远程线程注入)
  • 初探Service服务发现机制
  • 基础线性代数
  • 文档处理组件Aspose.Words 25.5全新发布 :六大新功能与性能深度优化
  • Python实现markdown文件转word
  • 【react+antd+vite】优雅的引入svg和阿里巴巴图标
  • Java在word中指定位置插入图片。
  • npm run dev 报错:Error: error:0308010C:digital envelope routines::unsupported
  • Flash烧录速度和加载配置速度(纯FPGA ZYNQ)
  • 使用ReactNative加载Svga动画支持三端【Android/IOS/Harmony】
  • FPGA 的硬件结构
  • 70年使用权的IntelliJ IDEA Ultimate安装教程
  • android 之 Tombstone
  • SSH/RDP无法远程连接?腾讯云CVM及通用服务器连接失败原因与超全排查指南
  • Mysql 身份认证绕过漏洞 CVE-2012-2122
  • 如何利用Elastic Stack(ELK)进行安全日志分析
  • 关于easyexcel动态下拉选问题处理
  • 大模型微调技术全景图:从全量更新到参数高效适配
  • 三表查询SQL怎么写?----小白初学+案例引入
  • SQL SERVER中获取外部数据的两种方法!
  • Postgresql常用函数操作
  • Flask-SQLAlchemy使用小结
  • AppWeb
  • JavaSec-XSS
  • 如何防止看板任务长期停滞不前