Skip to content

single-spa 与 qiankun

概述

在微前端生态中,single-spa 是最早的开源微前端框架之一,而 qiankun 则是基于 single-spa 封装的企业级微前端解决方案。本文将深入分析两者的核心机制、优缺点以及技术演进。

single-spa 核心机制

single-spa 的核心功能非常精简,主要完成两项工作:

  1. 加载微应用 - 通过用户提供的加载函数动态加载子应用
  2. 维护应用生命周期 - 管理微应用的初始化(bootstrap)、挂载(mount)和卸载(unmount)状态

虽然 single-spa 提供了微前端的基础能力,但在实际生产环境中暴露出诸多局限性。

single-spa 的核心问题

1. 对微应用的强侵入性

single-spa 采用 JS Entry 方式接入微应用,需要对现有项目进行较大改造:

  • 路由改造 - 为微应用路由添加特定前缀,避免路由冲突
  • 入口改造 - 修改应用挂载点,导出标准生命周期函数(bootstrapmountunmount)
  • 构建配置调整 - 修改 webpack 等打包工具配置

2. 构建产物限制与性能问题

JS Entry 方式要求将整个微应用打包成单个 JS 文件,这带来了严重的性能问题:

失去的优化能力:

  • ❌ 代码分割(Code Splitting)和按需加载
  • ❌ 首屏资源加载优化
  • ❌ CSS 独立提取与并行加载
  • ❌ 静态资源 CDN 缓存优化

版本更新的连锁反应:

当微应用修复 bug 并重新发布时,由于文件名包含 hash 值(如 app.[contenthash].js)会发生变化,导致:

  1. 微应用构建产物文件名改变
  2. 主应用配置中的微应用 JS 地址需要手动更新
  3. 主应用需要重新编译和发布

这种强耦合的发布流程在大型系统中难以接受,严重影响开发效率。

3. 样式隔离缺失

single-spa 未提供任何样式隔离机制,在多微应用系统中容易出现样式冲突:

  • 微应用之间的样式相互污染
  • 微应用与主应用的样式相互影响

现有解决方案的局限:

  • 只能通过约定式命名规范(如 BEM、CSS Modules)来规避
  • 对于已有的大型系统,改造成本极高
  • 无法从技术层面彻底解决问题

4. JavaScript 沙箱隔离缺失

single-spa 未实现 JS 运行时隔离,导致全局对象污染问题:

javascript
// 微应用 A
window.userInfo = { name: 'App A' };

// 切换到微应用 B 后,window.userInfo 依然存在
// 可能导致数据混乱或冲突

潜在风险:

  • 全局变量污染(windowdocument 等)
  • 全局事件监听器未清理
  • 定时器、异步任务泄漏

5. 资源预加载能力缺失

single-spa 不支持微应用资源的预加载(Prefetch),无法实现:

  • 在空闲时间预加载其他微应用资源
  • 提升应用切换的流畅度
  • 优化用户体验

6. 应用间通信机制缺失

single-spa 仅在注册时向微应用注入少量状态信息,不提供应用间通信能力:

  • 无内置的消息总线或事件系统
  • 需要开发者自行实现通信方案(如 CustomEvent、发布订阅模式等)

qiankun 的技术革新

HTML Entry 方案

为了解决 single-spa 的 JS Entry 痛点,qiankun 采用了 HTML Entry 方案,让微应用接入像使用 <iframe> 一样简单。

import-html-entry 核心原理

qiankun 依赖 import-html-entry 库实现 HTML Entry,其工作流程如下:

  1. 加载 HTML 模板 通过 HTTP 请求获取微应用的 index.html 内容

  2. 解析 HTML 结构 提取关键信息:

    • template - HTML 模板结构
    • scripts - 所有 <script> 标签的 URL 和内容
    • styles - 所有 <link><style> 的样式内容
    • entry - 入口脚本地址
  3. 处理样式资源

    • 远程加载 <link> 引用的 CSS 文件
    • 将外链样式转换为内联 <style> 标签
    • 替换模板中的样式占位符
  4. 返回可执行对象 向外暴露一个 Promise,resolve 后包含:

    • template - 处理后的 HTML 模板
    • assetPublicPath - 资源公共路径
    • execScripts - 脚本执行函数

qiankun 的集成与增强

qiankun 基于 import-html-entry 返回的对象,实现了完整的微前端能力:

核心流程:

  1. 挂载模板template 通过 DOM 操作插入主应用的容器节点

  2. 执行脚本并获取生命周期 调用 execScripts() 方法:

    • 在沙箱环境中执行微应用的 JS 代码
    • 获取微应用导出的生命周期钩子(bootstrapmountunmount)
  3. JavaScript 沙箱隔离 通过 execScriptsproxy 参数指定 JS 执行上下文:

    • 快照沙箱(SnapshotSandbox) - 单实例场景
    • 代理沙箱(ProxySandbox) - 多实例场景,基于 Proxy 实现

qiankun 的核心优势:

  • 零侵入接入 - 微应用无需打包成单文件
  • 样式隔离 - 支持 Shadow DOM 或作用域 CSS
  • JS 沙箱 - 自动隔离全局变量和副作用
  • 资源预加载 - 内置 prefetch 能力
  • 应用通信 - 提供 initGlobalState 全局状态管理

总结

特性single-spaqiankun
接入方式JS EntryHTML Entry
样式隔离❌ 不支持✅ 支持
JS 沙箱❌ 不支持✅ 支持
资源预加载❌ 不支持✅ 支持
应用通信❌ 需自行实现✅ 内置方案
侵入性
生产可用性需大量定制开箱即用

qiankun 在 single-spa 的基础上,通过 HTML Entry 和完善的沙箱机制,真正实现了生产级微前端解决方案,是目前企业应用的主流选择之一。