了解微前端架构中主应用与微应用、微应用之间的通信解决方案,需要具体、可落地的实现方法及适用场景。下面我会详细拆解主流的通信方案,包括原理、实现步骤和优缺点分析。
一、Props 传递(初始化数据通信)
核心概念(What)
Props 传递是主应用在注册 / 挂载微应用时,通过配置项直接向微应用传递数据的方式,适用于初始化静态数据的传递(如用户信息、全局配置)。
实现步骤(How)
1. 主应用传递 Props
在注册微应用时通过 props 字段传入数据:
javascript
// 主应用 main.js
registerMicroApps([
{
name: 'vue2-app',
entry: '//localhost:8081',
container: '#micro-app-container',
activeRule: '/vue2-app',
props: {
token: 'user-token-123', // 用户令牌
userInfo: { name: '张三', role: 'admin' }, // 用户信息
globalEventBus: eventBus // 传递事件总线(后续讲)
}
}
])
2. 微应用接收 Props
在微应用的 mount 生命周期中接收:
javascript
// Vue2 微应用 main.js
export async function mount(props) {
console.log('接收主应用Props:', props)
// 将Props存入Vuex或全局变量
store.commit('SET_USER_INFO', props.userInfo)
render(props)
}
// Vue3 微应用 main.js
export async function mount(props) {
// 将Props注入全局provide
app.provide('globalProps', props)
render(props)
}
优缺点
- 优点:简单直接,无额外依赖,适合初始化数据。
- 缺点:仅能单向传递(主→微),数据更新后微应用无法实时感知。
适用场景
- 微应用初始化所需的静态配置(如接口前缀、主题配置)。
- 用户登录态、权限信息等一次性传递的数据。
二、发布 - 订阅模式(EventBus,实时通信)
核心概念(What)
基于事件总线(EventBus)实现主 / 微应用间的双向通信:主应用提供全局 EventBus,微应用通过 Props 获取后订阅 / 发布事件,实现实时消息传递。
实现步骤(How)
1. 主应用创建全局 EventBus
javascript
// 主应用 src/utils/eventBus.js
class EventBus {
constructor() {
this.events = {} // 事件存储容器
}
// 订阅事件
on(eventName, callback) {
if (!this.events[eventName]) {
this.events[eventName] = []
}
this.events[eventName].push(callback)
}
// 发布事件
emit(eventName, data) {
if (this.events[eventName]) {
this.events[eventName].forEach(callback => callback(data))
}
}
// 取消订阅
off(eventName, callback) {
if (this.events[eventName]) {
this.events[eventName] = this.events[eventName].filter(cb => cb !== callback)
}
}
}
export default new EventBus()
2. 主应用传递 EventBus 给微应用
javascript
// 主应用 main.js
import eventBus from './utils/eventBus'
registerMicroApps([
{
name: 'vue2-app',
// ...其他配置
props: { eventBus } // 传递事件总线
}
])
// 主应用监听微应用事件
eventBus.on('micro-app:refresh-user', (data) => {
console.log('微应用触发刷新用户事件:', data)
// 主应用处理逻辑(如更新全局用户信息)
})
3. 微应用使用 EventBus 通信
javascript
// Vue2 微应用(mount生命周期中)
export async function mount(props) {
const { eventBus } = props
// 微应用发布事件给主应用
eventBus.emit('micro-app:notify', { msg: 'Vue2微应用已挂载' })
// 微应用订阅主应用事件
eventBus.on('main-app:user-update', (newUserInfo) => {
console.log('主应用更新用户信息:', newUserInfo)
// 微应用更新本地状态
})
render(props)
}
优缺点
- 优点:双向通信、实时性强,轻量级无依赖,支持任意应用间通信。
- 缺点:事件命名易冲突,需规范命名空间;无类型校验(可结合 TypeScript 优化)。
适用场景
- 实时交互场景(如微应用触发主应用全局弹窗、主应用通知微应用刷新数据)。
- 微应用之间的间接通信(通过主应用 EventBus 中转)。
三、全局状态管理(共享状态池)
核心概念(What)
通过中心化的状态管理库(如 Vuex/Pinia/Redux)维护全局状态,主应用作为状态管理者,微应用通过约定的接口读写状态,实现全局状态共享与同步。
实现步骤(How)
以 Pinia(Vue3)为例,主应用维护全局状态,微应用通过 Props 获取 Pinia 实例:
1. 主应用创建全局 Pinia 实例
javascript
// 主应用 src/store/index.js
import { createPinia } from 'pinia'
import { defineStore } from 'pinia'
// 定义全局共享Store
export const useGlobalStore = defineStore('global', {
state: () => ({
userInfo: null,
theme: 'light'
}),
actions: {
updateUserInfo(newInfo) {
this.userInfo = newInfo
},
toggleTheme() {
this.theme = this.theme === 'light' ? 'dark' : 'light'
}
}
})
export const pinia = createPinia()
2. 主应用传递 Pinia 给微应用
javascript
// 主应用 main.js
import { pinia, useGlobalStore } from './store'
// 主应用使用Pinia
const app = createApp(App)
app.use(pinia)
// 注册微应用时传递pinia实例
registerMicroApps([
{
name: 'vue3-app',
// ...其他配置
props: { pinia } // 传递Pinia实例
}
])
// 主应用操作全局状态
const globalStore = useGlobalStore()
globalStore.updateUserInfo({ name: '李四' })
3. 微应用使用全局 Pinia 状态
javascript
// Vue3 微应用 main.js
import { useGlobalStore } from '../../main-app/src/store' // 或通过npm包共享Store定义
export async function mount(props) {
const { pinia } = props
// 微应用安装主应用的Pinia实例
app.use(pinia)
// 微应用读取全局状态
const globalStore = useGlobalStore()
console.log('全局用户信息:', globalStore.userInfo)
// 微应用更新全局状态
globalStore.toggleTheme()
render(props)
}
优缺点
- 优点:状态集中管理,数据实时同步,支持复杂状态逻辑。
- 缺点:主 / 微应用需依赖相同的状态库,耦合度略高;跨技术栈(如 React 微应用)需额外适配。
适用场景
- 全局状态频繁变更的场景(如用户信息、系统主题、权限配置)。
- 多微应用需共享一致状态的复杂业务系统。
四、URL 参数传递(简单数据通信)
核心概念(What)
通过 URL 路径或查询参数传递数据(如 http://localhost:8080/vue2-app?page=1&size=10),适用于路由关联的简单数据传递。
实现步骤(How)
1. 主应用跳转时拼接参数
vue
<!-- 主应用导航组件 -->
<router-link to="/vue2-app?userId=1001">Vue2微应用(用户1001)</router-link>
2. 微应用解析 URL 参数
javascript
// Vue2 微应用(路由守卫或页面组件中)
import { useRoute } from 'vue-router' // Vue3
// 或 this.$route(Vue2)
export default {
mounted() {
// 解析查询参数
const userId = this.$route.query.userId
console.log('从URL获取用户ID:', userId)
// 解析路径参数(如 /vue2-app/user/1001)
const userId2 = this.$route.params.userId
}
}
优缺点
- 优点:简单无侵入,天然支持页面刷新后数据保留。
- 缺点:仅支持字符串数据,容量有限;敏感数据暴露在 URL 中不安全。
适用场景
- 路由跳转时传递页面参数(如分页、筛选条件)。
- 微应用初始化时的简单配置参数。
五、共享库(Shared Library)
核心概念(What)
将通信相关的接口、工具函数封装为独立的 npm 包(如 @company/micro-shared),主 / 微应用共同依赖该包,通过统一的 API 实现通信,适用于大型团队标准化通信。
实现步骤(How)
1. 创建共享 npm 包
javascript
// @company/micro-shared/src/index.js
class MicroShared {
constructor() {
this.eventBus = new EventBus() // 内置事件总线
this.globalState = {} // 简单全局状态
}
// 提供通信API
on(event, callback) { /* ... */ }
emit(event, data) { /* ... */ }
setGlobalState(key, value) { /* ... */ }
getGlobalState(key) { /* ... */ }
}
export const microShared = new MicroShared()
2. 主 / 微应用安装并使用共享库
bash
npm install @company/micro-shared --save
javascript
// 主应用
import { microShared } from '@company/micro-shared'
microShared.setGlobalState('token', 'abc123')
// 微应用
import { microShared } from '@company/micro-shared'
console.log(microShared.getGlobalState('token'))
优缺点
- 优点:标准化、可维护性强,适合多团队协作;便于版本管理和更新。
- 缺点:需额外维护 npm 包;版本升级需同步所有应用。
适用场景
- 大型企业级微前端架构,需要统一通信规范。
- 通信逻辑复杂,需沉淀复用的场景。
六、本地存储(LocalStorage/SessionStorage,慎用)
核心概念(What)
通过浏览器本地存储(LocalStorage/SessionStorage)存储共享数据,主 / 微应用监听 storage 事件实现数据变更通知。
实现步骤(How)
javascript
// 主应用写入数据
localStorage.setItem('micro-user-info', JSON.stringify({ name: '张三' }))
// 微应用监听数据变化
window.addEventListener('storage', (e) => {
if (e.key === 'micro-user-info') {
const userInfo = JSON.parse(e.newValue)
console.log('用户信息更新:', userInfo)
}
})
优缺点
- 优点:简单无需配置,支持跨会话数据保留(LocalStorage)。
- 缺点 :有 XSS 安全风险;
storage事件仅在不同标签页触发,同标签页需手动通知;数据非响应式。
适用场景
- 非敏感数据的持久化存储(如用户偏好设置)。
- 临时方案或简单场景(不推荐作为核心通信方式)。
总结
关键点回顾
- Props 传递:适合初始化静态数据,简单直接但不支持实时更新。
- EventBus(发布订阅):适合实时双向通信,轻量级但需规范事件命名。
- 全局状态管理:适合复杂全局状态共享,数据同步性好但耦合度略高。
- URL 参数:适合路由关联的简单数据,无侵入但容量有限。
- 共享库:适合大型团队标准化通信,可维护性强但需额外维护成本。
选择通信方案的核心原则:根据数据类型(静态 / 动态)、实时性要求、团队规模选择最合适的方式,复杂场景可组合多种方案(如 Props 传递初始化数据 + EventBus 处理实时交互)。