微前端
这篇笔记按掘金文章《微前端(无界)》的主线重新整理:先讲概念与方案,再聚焦无界(Wujie)的思路、接入和关键 API。
微前端概念
微前端是借鉴微服务思想,把一个大型前端应用拆成多个可独立开发、独立运行、独立部署的子应用,再由主应用在运行时组合。
微前端特性
| 特性 | 说明 |
|---|---|
| 技术栈无关 | 主应用不限制子应用技术栈(Vue/React/jQuery 等) |
| 独立开发部署 | 团队可分仓库、分流水线、分版本发布 |
| 增量升级 | 可按业务域渐进重构,不必一次性推倒重来 |
| 独立运行时 | 子应用之间状态和运行时应尽量隔离 |
常见场景
- 中后台聚合平台:主应用负责导航和编排,不同业务线接不同子应用。
- 多系统统一入口:把历史系统逐步纳入同一壳应用,降低用户切换成本。
微前端方案对比
| 方案 | 优点 | 缺点 |
|---|---|---|
iframe | 接入简单、天然强隔离 | DOM 割裂、通信复杂、路由体验差 |
qiankun | 生态成熟、工程能力完整 | 适配成本高,某些场景性能与隔离仍有边界 |
micro-app | 组件化使用体验较好,支持保活 | 路由与隔离在复杂场景仍需额外治理 |
EMP | 联邦模块共享能力强 | 沙箱能力弱,路由冲突与保活问题需自建 |
wujie | 路由同步、保活、预加载、隔离能力较均衡 | 仍有接入与适配成本(如部分库行为差异) |
文章强调的无界方向
文章的重点是:在“隔离、保活、路由、通信、vite 支持”这些诉求上,无界方案给出了一套更平衡的落地路径。
无界(Wujie)核心原理
用 WebComponent 承载子应用
主应用把子应用渲染到自定义元素中,编排逻辑和业务视图解耦。
CSS 隔离基于 Shadow DOM
子应用样式作用域被约束在 Shadow Root 内,降低样式串扰风险。
JS 隔离基于 iframe 沙箱
子应用在独立 iframe 环境运行,避免直接污染主应用全局对象。
通信通过 props / 事件总线 / proxy
主子应用通信不再依赖强耦合调用,而是通过可约定接口传输。
路由同步与保活
子应用路由可同步到主应用视角,切换后可保留状态,减少重复初始化。
预加载与调度优化
可提前拉取子应用资源,减轻首屏切换抖动;执行策略强调平衡响应和吞吐。
无界入门(Vue3 示例)
安装
Vue3 主应用
pnpm add wujie wujie-vue3Vue2 主应用
npm i wujie wujie-vue2 -SReact 主应用
npm i wujie wujie-react -S主应用注册
// main.ts
import { createApp } from 'vue'
import App from './App.vue'
import WujieVue from 'wujie-vue3'
const app = createApp(App)
app.use(WujieVue)
app.mount('#app')主应用渲染子应用
<template>
<WujieVue
name="sub-user"
url="http://127.0.0.1:5174"
:sync="true"
:alive="true"
:props="{ token: 'demo-token' }"
/>
</template>常用 API(setup / preload / start)
import { setupApp, preloadApp, startApp, destroyApp } from 'wujie'
setupApp({
name: 'sub-user',
url: 'http://127.0.0.1:5174',
exec: true,
sync: true,
})
preloadApp({
name: 'sub-user',
url: 'http://127.0.0.1:5174',
exec: true,
})
startApp({
name: 'sub-user',
url: 'http://127.0.0.1:5174',
el: '#subapp-root',
sync: true,
alive: true,
})
// 可选:卸载
destroyApp('sub-user')主子应用通信
1. props 注入
<WujieVue
name="sub-user"
url="http://127.0.0.1:5174"
:props="{ name: 'xm', age: 18 }"
/>// 子应用读取
console.log(window.$wujie?.props)2. bus 事件通信
主应用
import { bus } from 'wujie'
bus.$on('sub-user:ready', (payload) => {
console.log('from sub app:', payload)
})
bus.$emit('main:update', { theme: 'dark' })子应用
window.$wujie?.bus.$emit('sub-user:ready', { ok: true })
window.$wujie?.bus.$on('main:update', (payload) => {
console.log('from main app:', payload)
})实战治理清单(按文章痛点整理)
| 关注点 | 建议 |
|---|---|
| 样式隔离 | 优先使用 Shadow DOM;兜底再加命名空间约束 |
| 路由体验 | 开启路由同步,统一主子应用导航入口 |
| 首屏切换 | 对高频子应用开启 preload |
| 状态保留 | 对高频切换页面开启 alive 保活 |
| 通信协议 | 固定事件名规范(app:event)+ 统一 payload 类型 |
| 故障回收 | 子应用卸载时清理监听器、定时器、副作用 |
附:手搓一个 mini 微前端(主 + 两子应用)
这一段保留“最小实现思路”,用来理解框架背后的核心机制。
- 子应用统一导出
mount/unmount - 主应用按
location.pathname做路由分发 - 监听
popstate,并重写pushState/replaceState - 子应用切换时执行
unmount清理副作用 - 通过
Proxy+ 快照恢复做最小 JS 沙箱 - 用根类名前缀或 Shadow DOM 做 CSS 隔离
interface MicroApp {
name: string
activeRule: (pathname: string) => boolean
mount: (container: HTMLElement) => void
unmount: () => void
}