微前端与qiankun框架
微前端概述
微前端(Micro Frontends)是一种新兴的前端架构模式,它将大型的前端应用程序拆分为多个独立的、可管理的小型应用或服务。这种方法允许不同的团队使用不同的技术栈开发和维护各自的部分,同时还能将它们无缝地集成到一个统一的用户界面中。
为什么选择微前端
在我们的场景中,PDM系统(基于Vue)需要调用标签自动化系统(基于React)的Excalidraw画板编辑功能。由于技术栈的差异,传统方法难以实现两个项目的融合。微前端架构为我们提供了一种优雅的解决方案,使得不同技术栈的应用可以像搭积木一样组合在一起。
微前端的优势
- 技术栈无关:允许在同一个项目中使用不同的前端框架。
- 独立开发部署:各个微应用可以独立开发、测试和部署。
- 增量升级:可以逐步升级旧系统,降低风险。
- 团队自治:不同团队可以负责不同的微应用,提高开发效率。
微前端实现方案比较
1. iframe方案
优点
- 实现简单,是最古老且稳定的集成方式
- 天然的JS沙箱隔离
缺点
- URL不同步,影响浏览器的前进/后退功能
- UI不同步,难以实现跨iframe的UI交互
- 全局上下文隔离,跨应用通信较困难
- 性能较差,每次都需要重新加载资源
2. 使用script或fetch动态加载HTML
这种方法灵活性较高,但需要自行处理很多集成问题,如样式隔离、JS沙箱等。
3. qiankun框架(推荐)
qiankun是阿里巴巴开源的一个基于single-spa的微前端实现库,它提供了更完善的功能和更好的开发体验。
核心架构
qiankun 基于 Single-SPA 框架构建,采用了 JS 沙箱 + 样式隔离 + 预加载 的技术方案。
主要技术原理
1. 应用注册与路由匹配
// 应用注册机制
registerMicroApps([
{
name: 'reactApp',
entry: '//localhost:3000',
container: '#container',
activeRule: '/app-react',
}
])
原理:
- 通过
activeRule
配置路由匹配规则 - 监听浏览器路由变化(popstate、pushstate、replacestate)
- 当路由匹配时,触发对应应用的加载和渲染
2. 应用加载机制
HTML Entry 方案:
// 获取子应用的 HTML 内容
const html = await fetch(entry).then(res => res.text())
// 解析 HTML,提取 JS、CSS 资源
const { scripts, styles } = parseHTML(html)
原理:
- 通过
fetch
获取子应用的 HTML 文件 - 解析 HTML,提取
<script>
和<link>
标签 - 动态创建
<script>
标签加载 JS 资源 - 动态创建
<link>
标签加载 CSS 资源
3. JS 沙箱隔离
Proxy 沙箱:
class ProxySandbox {
constructor() {
const rawWindow = window
const fakeWindow = Object.create(null)
const proxy = new Proxy(fakeWindow, {
get(target, key) {
// 优先从 fakeWindow 获取,否则从真实 window 获取
return target[key] || rawWindow[key]
},
set(target, key, value) {
target[key] = value
return true
}
})
this.proxy = proxy
}
}
原理:
- 使用
Proxy
代理window
对象 - 子应用的全局变量存储在代理对象中
- 避免子应用污染主应用的全局环境
- 支持多实例沙箱(每个子应用独立沙箱)
4. 样式隔离
动态样式表:
// 动态添加样式
const styleElement = document.createElement('style')
styleElement.textContent = cssContent
document.head.appendChild(styleElement)
// 应用卸载时移除样式
const removeStyle = () => {
document.head.removeChild(styleElement)
}
原理:
- 子应用的 CSS 通过动态
<style>
标签注入 - 应用卸载时自动移除对应的样式
- 支持 CSS 前缀隔离(通过 postcss 插件)
5. 生命周期管理
应用生命周期:
// 子应用需要导出的生命周期
export async function bootstrap() {
// 应用初始化
}
export async function mount(props) {
// 应用挂载
}
export async function unmount() {
// 应用卸载
}
原理:
- 主应用通过
import()
动态加载子应用 - 调用子应用导出的生命周期函数
- 确保应用的正确加载、挂载和卸载
6. 通信机制
全局状态管理:
// 主应用设置全局状态
setGlobalState({ user: 'admin' })
// 子应用监听状态变化
onGlobalStateChange((state, prev) => {
console.log('状态变化', state, prev)
})
原理:
- 基于发布订阅模式
- 主应用维护全局状态
- 子应用可以订阅和修改全局状态
7. 预加载机制
// 预加载配置
prefetchApps([
{ name: 'reactApp', entry: '//localhost:3000' }
])
原理:
- 在空闲时间预加载子应用资源
- 提升用户访问子应用时的加载速度
- 支持多种预加载策略(all、async、manual)
优点
- 技术栈无关
- HTML Entry接入方式,让接入微应用像使用iframe一样简单
- 样式隔离,确保微应用之间样式不会互相影响
- JS沙箱,提供安全的运行环境
- 资源预加载,优化性能
- umi插件支持,简化接入流程
缺点
- 有一定的学习成本
qiankun框架接入指南
主应用配置
-
安装qiankun
yarn add qiankun # 或 npm i qiankun -S
-
注册微应用
import { registerMicroApps, start } from 'qiankun'; registerMicroApps([ { name: 'reactApp', entry: '//localhost:3000', container: '#container', activeRule: '/app-react', }, // ... 其他微应用 ]); start();
-
手动加载微应用(可选)
import { loadMicroApp } from 'qiankun'; loadMicroApp({ name: 'react', entry: '//localhost:8000', container: '#react', });
注意事项
- 子应用路由需要和主应用保持一致
- 主应用 hash 路由, 子应用也适用 hash 路由
子应用配置(以umi为例)
-
安装umi的qiankun插件
yarn add @umijs/plugin-qiankun -D
-
修改
.umirc.ts
配置文件export default defineConfig({ // hash 路由需要开启 // history: { // type: 'hash', // }, qiankun: { slave: {}, }, });
-
在
app.ts
中导出生命周期钩子export const qiankun = { // 应用加载之前 async bootstrap(props) { console.log('react bootstrap', props) }, // 应用 render 之前触发 async mount(props) { console.log('react mount', props) props.onGlobalStateChange((state, prev) => { // state: 变更后的状态; prev 变更前的状态 console.log(state, prev) }) props.setGlobalState({ key: 'react 222' }) }, // 应用卸载之后触发 async unmount(props) { console.log('react unmount', props) }, /** * 可选生命周期钩子,仅使用 loadMicroApp 方式加载微应用时生效 */ async update(props) { console.log('react update', props) }, }
注意事项
- 确保子应用的路由与主应用保持一致
- 如果主应用使用hash路由,子应用也应使用hash路由
- 处理好应用间的通信机制
- 注意样式隔离和JS沙箱的使用
结论
微前端架构,特别是使用qiankun框架,为我们提供了一种强大的方式来集成不同技术栈的应用。虽然有一定的学习和配置成本,但它带来的灵活性和可维护性是值得的。在我们的PDM系统与标签自动化系统集成的场景中,qiankun将是一个理想的选择。