WUJIE VS QIANKUN 微前端框架选型(一)
引言
两个不同UI架构的项目均开发完成后,遭遇需要将两个项目合并成一个的迭代开发需要。
一个react一个vue,一个是elementui,一个是antdesign……
而且两个项目业务复杂度均比较高。如果直接合并修改语法糖成本过高。
于是…
调研微前端
微前端通过将项目拆分为多个独立自治的微应用,解决这些问题:
技术栈无关:支持 Vue、React、Angular 等框架混合开发
独立部署:各团队可独立开发、测试、发布
渐进升级:允许逐步重构旧系统
动态加载:按需加载减少首屏耗时
逆向思维,降多个不同技术栈开发的项目,视为微应用进行组合,也是可以的。
框架选型
首批先调研和对比了乾坤和腾讯无界
实现方式对比
特性 | 无界(Momentum) | 乾坤(Qiankun) |
---|---|---|
技术实现 | WebComponents + iframe | single-spa + proxy + function-based sandbox |
样式隔离 | 依赖 WebComponent 原生影子DOM | JS 沙箱 + 实验性样式隔离 |
浏览器兼容性 | IE11+(需处理 iframe 弹窗) | 支持 IE11(通过 polyfill) |
学习成本 | 极低(接近原生开发) | 中等(需理解生命周期函数) |
最佳适用场景 | 中小型项目、快速集成 | 大型复杂项目、多团队协作 |
核心特性对比
1. 样式隔离
无界:利用 WebComponent 的影子DOM自动隔离样式
乾坤:需开启严格样式隔离(sandbox: { strictStyleIsolation: true }
),否则可能污染全局样式
2. JS 沙箱
无界:通过 iframe 天然隔离,但跨帧通信成本较高
乾坤:采用函数代理沙箱,性能更优但需注意变量泄漏
3. 动态路由
无界:支持动态注册路由,适合频繁变化的导购系统
乾坤:依赖主应用路由配置,更适合固定入口的场景
关键区别
无界:无需显式启动,注册即自动加载
乾坤:需调用 start()
激活沙箱环境
样式隔离:无界依赖 WebComponent 影子DOM,乾坤需配置 sandbox: { strictStyleIsolation: true }
主应用配置
1. 创建主应用(Vue 3)
vue create main-app
cd main-app
npm install momentum-ui # 无界框架
npm install qiankun # 乾坤框架
2. 目录结构
main-app/
├── public/
│ └── index.html
├── src/
│ ├── components/
│ │ └── NavBar.vue
│ ├── App.vue
│ ├── main.js
│ └── ...
├── package.json
无界框架实现
1、main.js 配置
import { createApp } from'vue'
import App from'./App.vue'
import NavBar from'./components/NavBar.vue'
import { registerMicroApps } from'momentum-ui'const app = createApp(App)
app.component('NavBar', NavBar)
app.mount('#app')// 注册子应用
registerMicroApps([{name: 'project',entry: '//localhost:8081',activeRule: '/project',container: '#subapp-container'},{name: 'demand',entry: '//localhost:8082',activeRule: '/demand',container: '#subapp-container'}
])
2. 导航组件(src/components/NavBar.vue
)
<template><nav><router-link to="/project">项目管理</router-link><router-link to="/demand">需求管理</router-link></nav>
</template>
注:每个系统还有很多菜单项,缩减成两个
3. 主应用模板(public/index.html
)
<body><div id="app"><NavBar /><div id="subapp-container"></div></div>
</body>
乾坤框架实现
1. 主应用配置(src/main.js
)
import { createApp } from'vue'
import App from'./App.vue'
import NavBar from'./components/NavBar.vue'
import { registerMicroApps, start } from'qiankun'const app = createApp(App)
app.component('NavBar', NavBar)
app.mount('#app')// 注册子应用
registerMicroApps([{name: 'project',//vue2的entry: '//localhost:8081',activeRule: '/project',container: '#subapp-container',props: { allowRouter: true }},{name: 'demand',//vue3的entry: '//localhost:8082',activeRule: '/demand',container: '#subapp-container'}
])// 启动乾坤
start()
子应用开发
1、无界
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'if (window.__POWERED_BY_MOMENTUM__) {__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_MOMENTUM__
}ReactDOM.render(<App />, document.getElementById('root'))
2、乾坤
import React from'react'
import ReactDOM from'react-dom'
import App from'./App'let instance = nullfunction render(props) {ReactDOM.render(<App {...props} />, document.getElementById('root'))
}if (!window.__POWERED_BY_QIANKUN__) {render()
}exportasyncfunction bootstrap() {
console.log('React 子应用启动')
}
exportasyncfunction mount(props) {
console.log('React 子应用挂载')render(props)
}
exportasyncfunction unmount() {ReactDOM.unmountComponentAtNode(instance.container.querySelector('#root'))
console.log('React 子应用卸载')
}
部署到生产
构建顺序:
先构建主应用,再依次构建子应用
使用带哈希的指纹版本避免缓存问题
Nginx 配置示例:
server {listen 80;location / {root /path/to/main-app/dist;try_files $uri $uri/ /index.html;}location /project/ {proxy_pass http://localhost:8081;}location /demand/ {proxy_pass http://localhost:8082;}
}
跨域处理:
子应用需设置 Access-Control-Allow-Origin
推荐使用 CDN 加速静态资源加载
适用场景分析
乾坤
适用场景:
需要动态加载多个子应用的中大型项目。
团队技术栈统一(如 React/Vue),且能接受较高的子应用适配成本。
局限性:
不支持多应用保活、Vite 子应用,沙箱性能问题在高频交互场景下显著。
无界
适用场景:
快速集成老项目或混合框架(如 Vue2 + Vue3 + React)。
需要同时激活多个子应用或保留子应用状态(如后台管理系统)。
对性能和兼容性要求较高(如兼容 IE9)。
局限性:
弹窗受 iframe 限制(仅降级模式下无法全局覆盖,正常模式下子应用DOM与主应用同源,可以全局展示)。
新推出的框架,更新迭代较慢,可能存在部分问题?
总结
乾坤:适合需要动态路由管理和复杂状态共享的大型项目,但需接受较高的改造和维护成本。
无界:适合追求低接入成本、高性能隔离和多应用协作的场景,尤其适合快速迭代和混合技术栈项目。
最后这俩个都没有选,so未完待续……