簡介
跨MFE通訊是微前端最大的挑戰。每個 MFE 都在自己的運行時中運行,沒有共享記憶體。本文介紹安全通訊模式。
1. 黃金法則
MFE 應該是松耦合——透過合約進行通信,而不是共享狀態。
❌ Shared Global State:
window.globalStore = { cart: { items: [...] } }
→ Coupling nightmare, race conditions
✅ Event-based Communication:
MFE A publishes: "cart:item-added" { productId, qty }
MFE B subscribes: update cart badge
→ Loosely coupled, observable
2. 溝通模式
2.1 自訂事件(瀏覽器本機)
// Product MFE - Publish
window.dispatchEvent(new CustomEvent('cart:item-added', {
detail: { productId: '123', name: 'Laptop', price: 999 }
}));
// Cart MFE - Subscribe
useEffect(() => {
const handler = (e) => {
setCartItems(prev => [...prev, e.detail]);
};
window.addEventListener('cart:item-added', handler);
return () => window.removeEventListener('cart:item-added', handler);
}, []);
2.2 事件匯流排(自訂)
class EventBus {
private handlers: Map<string, Set<Function>> = new Map();
on<T>(event: string, handler: (payload: T) => void) {
if (!this.handlers.has(event)) this.handlers.set(event, new Set());
this.handlers.get(event)!.add(handler);
return () => this.handlers.get(event)?.delete(handler);
}
emit<T>(event: string, payload: T) {
this.handlers.get(event)?.forEach(h => h(payload));
}
}
export const eventBus = new EventBus();
2.3 基於 URL 的狀態
/products?category=electronics&sort=price
→ URL là "shared state" tự nhiên: bookmarkable, shareable, no coupling
2.4 瀏覽器存儲
// Shared preferences via localStorage
localStorage.setItem('user:preferences', JSON.stringify({
currency: 'VND', language: 'vi', theme: 'dark'
}));
3. 國家所有權規則
| 狀態 | 業主 | MFE 如何存取 |
|---|---|---|
| 授權狀態 | 殼牌 | 背景/事件 |
| 購物車商品 | 購物車 MFE | 活動 |
| 產品資料 | 產品MFE | 未分享 |
| 使用者偏好 | 殼牌 | 本地儲存 + 事件 |
| URL 參數 | 外殼(路由器) | 網址 |
| 使用者介面主題 | 殼牌 | CSS 變數 |
4. 契約優先的通信
// shared-types/events.ts
interface CartItemAddedEvent {
type: 'cart:item-added';
payload: { productId: string; name: string; price: number; quantity: number; };
}
interface CartUpdatedEvent {
type: 'cart:updated';
payload: { itemCount: number; total: number; };
}
5. 最佳實踐
Mỗi MFE nên:
✅ Fetch dữ liệu riêng (own API calls)
✅ Manage state riêng (local state)
✅ Render independently
✅ Graceful degradation
Mỗi MFE KHÔNG nên:
❌ Import components từ MFE khác
❌ Access DOM của MFE khác
❌ Share runtime state qua window/global
❌ Assume MFE khác đã loaded
總結
- 自訂事件 — 簡單,瀏覽器原生
- 事件匯流排 — 類型化、可測試
- URL — 最適合導航狀態
- localStorage — 使用者首選項
- 規則:每個 MFE 管理自己的狀態,透過事件進行通信
下一篇文章: 第 15 課:設計系統和共享 UI — 保持 UX 一致