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

微前端MFE: 通过共享模块通信(模块联邦Module Federation)

背景

传统微前端中,不同子应用彼此完全独立,通信主要通过事件、消息总线等方式。随着模块联邦(Module Federation)技术的发展,可以在多个微前端应用间动态共享模块,实现模块级别的调用和通信,打破边界。


核心思想

  • 利用 Webpack Module Federation 机制,多个应用间共享和暴露模块(函数、组件、状态管理实例等)。

  • 通过导入其他应用暴露的模块,直接调用对方的功能或状态,达成通信目的。


具体实现步骤

1. 应用间暴露接口模块

remote 应用通过 Module Federation 配置,暴露一个模块,比如状态管理实例、工具函数或事件总线。

// webpack.config.js (remote 应用)
module.exports = {// ...plugins: [new ModuleFederationPlugin({name: 'remoteApp',filename: 'remoteEntry.js',exposes: {'./EventBus': './src/eventBus.js', // 暴露一个事件总线模块'./sharedState': './src/sharedState.js' // 也可以暴露状态实例},shared: ['react', 'react-dom'], // 共享依赖}),],
};
2. host 应用动态加载并调用 remote 模块

在主应用或其他子应用里,动态加载这个暴露的模块,并使用它完成通信。

// host 应用中,动态加载 remote 应用暴露的模块
import('remoteApp/EventBus').then(eventBusModule => {const eventBus = eventBusModule.default;// 订阅事件eventBus.on('some-event', (data) => {console.log('收到 remote 应用消息:', data);});// 触发事件,通知 remote 应用eventBus.emit('host-event', { msg: 'Hello from host' });
});

共享状态的例子

比如两个应用共享同一个 sharedState 实例(可以是 Redux store、MobX store 或自定义状态管理)。

// remote 应用 sharedState.js
import { makeAutoObservable } from 'mobx';class SharedState {data = 0;constructor() {makeAutoObservable(this);}setData(value) {this.data = value;}
}const sharedState = new SharedState();
export default sharedState;

host 应用调用:

import('remoteApp/sharedState').then(sharedState => {console.log(sharedState.data);sharedState.setData(42);
});

完整示例

基于 Module Federation 共享事件总线 ,演示 remote-app 如何在组件内监听 host-to-remote 事件,并展示消息。

1. remote-app 结构和代码

假设前端框架用的是 React,remote-app 目录结构:

remote-app/src/eventBus.jsApp.jsxindex.jswebpack.config.jspackage.json

1.1 webpack.config.js
const { ModuleFederationPlugin } = require('webpack').container;
const path = require('path');module.exports = {mode: 'development',entry: './src/index.js',devServer: {port: 3001,historyApiFallback: true,},output: {publicPath: 'auto',path: path.resolve(__dirname, 'dist'),},module: {rules: [{test: /\.jsx?$/,loader: 'babel-loader',exclude: /node_modules/,},],},resolve: {extensions: ['.js', '.jsx'],},plugins: [new ModuleFederationPlugin({name: 'remoteApp',filename: 'remoteEntry.js',exposes: {'./eventBus': './src/eventBus.js',},shared: ['react', 'react-dom', 'mitt'],}),],
};

1.2 src/eventBus.js
import mitt from 'mitt';const eventBus = mitt();export default eventBus;

1.3 src/App.jsx
import React, { useEffect, useState } from 'react';
import eventBus from './eventBus';export default function App() {const [message, setMessage] = useState('');useEffect(() => {// 监听 host 应用发来的事件const handler = (data) => {setMessage(data.msg);console.log('remote-app 收到 host 发送的消息:', data);};eventBus.on('host-to-remote', handler);// 清理订阅return () => {eventBus.off('host-to-remote', handler);};}, []);// 远程主动发送消息给 hostuseEffect(() => {setTimeout(() => {eventBus.emit('remote-to-host', { msg: 'Hello from remote-app React component!' });}, 3000);}, []);return (<div><h2>Remote App (React)</h2><p>收到 host 的消息: {message || '暂无消息'}</p></div>);
}

1.4 src/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);

2. host-app 结构和代码

host-app 目录结构类似:

host-app/src/index.jswebpack.config.jspackage.json

2.1 webpack.config.js
const { ModuleFederationPlugin } = require('webpack').container;
const path = require('path');module.exports = {mode: 'development',entry: './src/index.js',devServer: {port: 3000,historyApiFallback: true,},output: {publicPath: 'auto',path: path.resolve(__dirname, 'dist'),},plugins: [new ModuleFederationPlugin({name: 'hostApp',remotes: {remoteApp: 'remoteApp@http://localhost:3001/remoteEntry.js',},shared: ['mitt'],}),],
};

2.2 src/index.js
// host 应用中动态加载 remote-app 暴露的事件总线
import('remoteApp/eventBus').then((module) => {const eventBus = module.default;// 监听 remote 发来的消息eventBus.on('remote-to-host', (data) => {console.log('host-app 收到 remote 发送的消息:', data);});// 发送消息给 remote 应用setTimeout(() => {eventBus.emit('host-to-remote', { msg: 'Hi from host-app after 5 seconds!' });}, 5000);
});

3. 启动顺序
  1. 启动 remote-app(端口3001)

  2. 启动 host-app(端口3000)

  3. host-app 会动态加载 remote-app 的事件总线模块

  4. remote-app React 组件会监听 host-to-remote 事件,5秒后 host-app 发送消息,remote-app 显示消息

  5. remote-app 3秒后发消息给 host-app,host-app 控制台打印消息


优点

  • 模块级别通信,直接调用函数、操作状态,不必通过事件转发或序列化。

  • 代码复用性强,减少重复实现。

  • 易于维护,接口清晰。

  • 支持多种通信模式(事件总线、状态管理、工具函数等)。


缺点/挑战

  • 依赖构建配置复杂,需统一 webpack Module Federation 配置。

  • 应用间耦合度稍高,不适合完全独立解耦的场景。

  • 需要解决共享依赖版本冲突问题(React、ReactDOM 等)。

  • 只能用于同一浏览器上下文内(单页面应用或 iframe 内嵌需额外配置)。


适用场景

  • 多个微前端应用间需要共享状态或业务逻辑。

  • 需要高度复用组件或工具库。

  • 使用 Module Federation 技术栈。

  • 微前端加载在同一页面,且能共享同一个 JS 运行时环境。

http://www.lryc.cn/news/573566.html

相关文章:

  • 【机器学习四大核心任务类型详解】分类、回归、聚类、降维都是什么?
  • 【论文阅读笔记】TransparentGS:当高斯溅射学会“看穿”玻璃,如何攻克透明物体重建难题?
  • 【Nature Communications】超高介电常数材料 Hf0.5Zr0.5O2(HZO)
  • Oracle 11G RAC修改public ip vip private ip
  • 【数据治理】要点整理-《数据管理能力成熟度评估模型》国家标准(GB/T 36073—2018)
  • Linux的文件权限
  • 16_设备树中的remote-endpoint演示基于视频字符设备Linux内核模块
  • python源码:执行pdf合并/分页/图片管理功能
  • 计算机网络课程设计--基于TCP协议的文件传输系统
  • 案例练习二
  • rom定制系列------红米note11 5G版 MTK芯片强解bl锁修复bug 官方系统 面具root批量线刷版
  • 魂斗罗ost 游戏全合集8GB
  • 微服务网关/nacos/feign总结
  • Mybatis-Plus支持多种数据库
  • 使用模板创建uniapp提示未关联uniCloud问题
  • LeapMotion-PhysicalHandsManager 类详解
  • 【后端】负载均衡
  • 怎么让二级域名绑定到wordpesss指定的页面
  • Linux系统基本操作指令
  • C++指针(二)
  • 【算法】【优选算法】优先级队列
  • 跨个体预训练与轻量化Transformer在手势识别中的应用:Bioformer
  • 告别线程爆炸:我如何用 Spring WebFlux 构建一个端到端响应式应用
  • 编程基础:调用访问
  • CSP-S 模拟赛一总结(T1、T2)
  • Odoo 17 Many2one字段内联编辑完整实现方案
  • 2025最新Python 100个常用函数在线体验项目
  • 微处理器原理与应用篇---计算机系统的性能测试
  • python中学物理实验模拟:凸透镜成像和凹透镜成像
  • Spring-MyBatis基本操作