Qiankun 微前端框架学习笔记
Qiankun 是目前业界比较成熟的一套微前端框架方案,最早由阿里内部衍生并开源。它本质上基于 single-spa 的微前端模型进行了一层封装,提供了更完备的沙箱、预加载以及零配置集成体验等特性。在微前端架构中,主应用(基座)和子应用通常需要在同一个页面中协作与运行,而 Qiankun 核心解决的正是如何优雅地加载与卸载子应用、同时又保证子应用间的隔离(如全局变量、样式等),并且在主应用和子应用之间实现通信和数据传递。

概览
Qiankun 是目前业界比较成熟的一套微前端框架方案,最早由阿里内部衍生并开源。它本质上基于 single-spa 的微前端模型进行了一层封装,提供了更完备的沙箱、预加载以及零配置集成体验等特性。在微前端架构中,主应用(基座)和子应用通常需要在同一个页面中协作与运行,而 Qiankun 核心解决的正是如何优雅地加载与卸载子应用、同时又保证子应用间的隔离(如全局变量、样式等),并且在主应用和子应用之间实现通信和数据传递。
下面将从以下几个维度对 Qiankun 进行分析和解读:
- 微前端的背景与核心需求
- Qiankun 的总体设计思路
- 沙箱与隔离机制
- 路由与生命周期管理
- 子应用加载与资源处理
- 数据通信与共享
- 预加载和性能优化
- 与 single-spa 的关系
- 总结与思考
微前端背景与核心需求
传统单体应用(Monolithic Application)在规模不断扩张时,常常面临以下问题:
- 复杂度提升:多人协作时,代码耦合度高、难以维护,发布节奏不同步。
- 技术栈难以统一升级:当旧项目需要演进到新技术栈时,往往需要大规模重构。
- 部署/版本冲突:一次部署往往影响整个应用,即使只改动一小部分,也需要整个应用回归测试。
微前端思想与微服务类似,将一个大型前端应用拆分成若干相对独立的子应用(子模块),各子应用可以:
- 独立开发/构建/部署
- 独立使用各自的技术栈(React/Vue/Angular 等)
- 独立维护自己的版本演进和部署节奏
微前端的核心需求可以总结为:
- 独立加载与运行:不同子应用互不干扰,能被主应用动态挂载和卸载。
- 样式与全局作用域隔离:解决冲突,避免修改共享的 window、document、样式等。
- 统一的路由与导航管理:主应用需要统一管理页面路径,以实现前端单页应用(SPA)的用户体验。
- 数据共享与通信:支持在主应用和子应用、或子应用之间传递和共享数据。
Qiankun 的总体设计思路
Qiankun 的设计理念可以用一句话概括:在简单的开发体验基础上,为子应用提供基于沙箱的运行和隔离能力,并且最大程度地保证与 single-spa 的兼容。
主要体现为以下几点:
- 易用性:在使用上,Qiankun 提供了诸如
registerMicroApps
、start
等较高层的 API,开发者只需进行简单注册和配置即可快速让多个子应用接入。 - 沙箱机制:是 Qiankun 的核心价值所在,能够保证多个子应用在同一个页面中运行时,能尽可能隔离全局变量和样式污染。
- 基于生命周期的管理:借助 single-spa 的理念,子应用具有统一的
bootstrap
、mount
、unmount
等钩子函数,易于集中管理,也方便应用做各种初始化和销毁逻辑。 - 预加载与性能优化:Qiankun 支持在空闲时预先下载子应用静态资源,提高子应用首次打开时的速度体验。
- 技术栈无关:理论上,不管子应用是 React、Vue 还是 Angular,都可以通过特定的包装方式接入 Qiankun。
沙箱与隔离机制
为什么需要沙箱?
在单页应用中,如果同时加载多个子应用,它们都运行在同一个 window
上,各自的脚本、样式、全局变量、事件监听都有可能互相干扰。尤其当子应用数量或规模增多之后,这种全局作用域共享会导致难以排查的冲突,给调试和维护带来极大困扰。沙箱机制就是为了解决此类问题,通过“劫持”或“代理”全局变量访问,在应用被挂载时将访问作用域限制在应用自身需要的范围。
Qiankun 的沙箱类型
Qiankun 主要有两种沙箱实现机制(也会根据浏览器能力进行降级):
- Proxy 沙箱(一般称为
singular
模式和legacy
模式)- 基于 ES6 的
Proxy
对象实现,通过 Proxy 代理window
上的访问和修改操作,在子应用内部读写全局变量时,会映射到一份独立的内存空间。 - 只要浏览器支持 Proxy,就能利用它实现动态沙箱,在不同子应用切换时关闭/重置沙箱。
- 当子应用被卸载后,可以快速释放或重置相关全局状态。
- 基于 ES6 的
- 快照沙箱(仅在不支持 ES6 Proxy 的老旧环境下使用)
- 通过在子应用挂载前后“快照”全局对象,并在卸载时进行对比和还原,间接实现沙箱效果。
- 由于快照沙箱需要对比 window 的所有改动,性能和准确性不如 Proxy 沙箱好,因而仅作为降级方案。
沙箱的实现原理
以 Proxy 沙箱为例,当我们加载某个子应用时,Qiankun 会:
- 创建一个
proxy
对象用于代理 window 的属性访问,内部有一个 record 用于存储被子应用修改的全局变量。 - 读操作:如果子应用在执行时访问某个全局变量
window.xxx
,先检查沙箱自身记录是否有,如果没有则再去访问真实的 window,保证对内建 API 的获取不受影响。 - 写操作:若子应用去设置
window.xxx = ...
,则实际上会写进沙箱内部的 record,而不污染外部真实的 window。 - 当该子应用被卸载或切换到下一个子应用时,可以禁用当前沙箱,后续对沙箱的写操作将失效,实现彻底的子应用隔离。
路由与生命周期管理
Qiankun 核心使用了 single-spa 的理念:基于路由进行应用激活,并在激活时调用子应用的生命周期函数。
- 注册子应用:通过
registerMicroApps(apps, lifeCycles?)
配置子应用信息,每个子应用包括:name
:应用名称entry
:应用入口(HTML 或 JS 地址)activeRule
:匹配激活路由container
:渲染容器- 等等…
- 启动主应用:调用
start()
方法启动框架。Qiankun 会监听浏览器路由变化,当 URL 匹配到某个子应用的activeRule
时,就会:- 拉取子应用资源(HTML/JS/CSS)
- 执行子应用的
bootstrap
生命周期做初始化 - 执行
mount
将子应用挂载到指定容器
- 销毁或切换:当路由切走时,会执行子应用的
unmount
,将其从页面和内存中卸载,释放相关资源。
生命周期函数(bootstrap / mount / unmount)通常由子应用自己实现,比如在 mount
中做 DOM 渲染,unmount
中解绑事件等。
子应用加载与资源处理
加载策略
Qiankun 在加载子应用时,会先获取子应用的 HTML 入口,然后在解析 HTML 的过程中提取脚本和样式,并动态插入到主应用页面中。这里会对每个 <script>
、<link>
等标签进行处理,以便精确地控制它们的执行顺序和作用域。
动态插入与执行时机
- Qiankun 会先解析并收集子应用的所有脚本和样式链接,做一些去重和缓存。
- 当子应用被激活时,才真正执行这些脚本,并将 CSS 样式插入到页面中。结合沙箱机制,脚本里面对全局变量的访问不会影响主应用和其他子应用。
样式隔离
Qiankun 默认不会为每个子应用做严格的 CSS Scope(比如像 Shadow DOM 那样彻底隔离),但通过加前缀或命名规范可以在一定程度上避免样式冲突。此外也有社区提供了更多样式隔离的解决方案,比如动态给 CSS 选择器加上特定前缀,但通常会影响性能或兼容性,需要权衡。
数据通信与共享
当主应用和子应用之间需要共享一些全局数据(比如用户登录信息、权限、公共状态等),Qiankun 提供了三种常用的做法:
- props 传递:在注册子应用时,可以通过
props
字段把数据或方法透传给子应用;子应用可直接在生命周期函数的props
参数中获取到。 - 全局数据通信:Qiankun 提供了
initGlobalState
等方法创建全局数据仓库,主应用和各子应用都可订阅数据变化并触发更新,从而共享一份全局可观测数据。 - 自定义事件或消息总线:可以通过浏览器原生的
window.postMessage
或者类似 Pub/Sub 的消息总线进行通信,Qiankun 并没有做特别的封装,可以自由发挥。
预加载和性能优化
Qiankun 有一个非常实用的特性:预加载子应用。在主应用空闲时,利用浏览器空闲时间与网络带宽,提前拉取并解析子应用的静态资源(HTML/JS/CSS),这样在真正激活子应用时就只需要执行脚本,无需再次下载,提高了首屏速度。
- 在调用
start({ prefetch: true })
时,Qiankun 会在主应用启动后、空闲时,对已注册但尚未激活的子应用进行预下载。 - 对于大型前端应用场景,这通常可以显著优化用户切换到子应用时的加载体验。
与 single-spa 的关系
Qiankun 最初就是构建在 single-spa 之上,两者的核心差异在于:
- 封装程度不同:
- single-spa 本身提供了非常原生的生命周期管理,但对沙箱或样式隔离等没有做太多处理,需要开发者自己去实现。
- Qiankun 在 single-spa 基础上封装了一系列开箱即用的能力,如 Proxy 沙箱、预加载、全局状态管理等,大幅简化了接入微前端的工作量。
- 使用方式:
- single-spa 更像一个微前端内核,需要开发者在配置路由、加载器、沙箱方面编写更多自定义逻辑;
- Qiankun 则倾向“一站式”,通过简单的
registerMicroApps
、start
等 API,就可以让多个子应用跑起来,而且默认拥有良好的隔离能力。
- 社区生态:
- single-spa 在海外社区相对活跃,文档体系成熟;
- Qiankun 在国内社区使用率高,阿里系和大厂在内部也有大量实践,中文文档/案例丰富。
总结与思考
- 核心思路:Qiankun 是一个基于 single-spa 升级而来的微前端解决方案,其设计思想集中于:使用沙箱机制实现前端应用的强隔离,并封装掉复杂的资源加载与路由管理细节,给开发者提供相对简单的一键式微前端体验。
- 沙箱重中之重:微前端的灵魂在于保证不同子应用之间的隔离与独立运行。Qiankun 通过 Proxy 沙箱最大化地减少了全局污染的风险,并在主应用移除子应用时能够释放或还原全局环境。
- 零配置和易用性:对大部分项目而言,只需提供子应用的入口地址、激活路由和挂载容器,就可以快速让微前端跑起来,降低了改造和迁移成本。
- 性能优化:预加载特性提升了应用切换时的响应速度,适用于多数 B 端管理系统场景。
- 局限与挑战:
- 子应用间如果需要复杂的数据通信或共享模型,仍需要开发者自行设计。
- 样式隔离并不是彻底的 Shadow DOM 级别隔离。
- 当子应用很多且体积很大时,资源预加载策略和内存占用是需要重点关注和权衡的。
- 在某些情况下(比如一些第三方库会直接操作全局变量),沙箱无法完全封装所有外部副作用,需要手动处理。
总的来看,Qiankun 是当前国内非常流行且成熟的微前端解决方案,能很好地解决多技术栈并存、团队独立开发部署、渐进升级的需求。它从微前端架构的思想出发,配合完整的沙箱隔离和易用的接口,实现了应用解耦与协作,大幅简化微前端的上手难度。对多数中大型前端项目而言,如果有需求将前端拆分为多个子应用独立部署,Qiankun 都会是一个值得尝试的选择。