2、技术选型对比:iframe、Web Components、Module Federation、qiankun、single-spa 的优缺点分析

做微前端,第一步就是选技术。这一步选错了,后面全是坑。

我见过不少团队,一上来就拍脑袋选 qiankun,结果项目跑起来发现根本不需要沙箱隔离。也见过硬上 Module Federation 的,最后被构建配置搞到崩溃。

今天我把主流的五个方案掰开揉碎讲清楚。你听完心里就有数了。

2.1 iframe:最古老,也最被低估

iframe 其实是被骂得最惨的方案。很多人一听 iframe 就摇头,说性能差、通信难、SEO 不行。

但说实话,iframe 的隔离性是最好的。没有之一。

核心优势:

  • 天然隔离:CSS、JS、DOM 完全独立,互不干扰
  • 子应用崩溃不影响主应用
  • 几乎零改造,老项目直接嵌入

我在项目中遇到过这样的情况:一个用了 jQuery 1.x 的老系统,要集成到 React 18 的新平台里。用 qiankun 跑起来各种报错,最后直接用 iframe 嵌入,十分钟搞定。

但 iframe 的缺点也很明显:

  • 通信成本高:postMessage 用起来很别扭,不像函数调用那么自然
  • 路由不同步:刷新页面后,iframe 里的状态就丢了
  • 弹窗/遮罩层出不来:子应用的弹窗只能局限在 iframe 区域内
  • 性能开销:每个 iframe 都是一个独立的浏览器上下文,内存占用高

我的建议:

如果你只是临时集成一个第三方系统,或者子应用完全独立、不需要和主应用深度交互,iframe 反而是最省心的方案。别被技术鄙视链带偏了。

2.2 Web Components:标准化的未来,但现实很骨感

Web Components 是 W3C 的标准规范。理论上,它可以让不同框架的组件共存。

但实际用起来,嗯……有点尴尬。

先看优点:

  • 标准化:浏览器原生支持,不需要额外框架
  • Shadow DOM 隔离:样式和 DOM 完全隔离
  • 跨框架复用:React、Vue、Angular 都能用

再看缺点:

  • 生态不成熟:UI 组件库对 Web Components 的支持很差
  • 框架集成麻烦:React 对 Web Components 的支持一直有问题,事件绑定、属性传递都需要额外处理
  • 性能问题:大量使用 Shadow DOM 会导致渲染性能下降
  • 调试困难:Shadow DOM 里的样式和 DOM 结构很难调试

避坑指南:

我曾经在一个项目中尝试用 Web Components 做微前端,结果发现 Ant Design 的组件根本没法用。因为 Ant Design 的样式是全局的,进不了 Shadow DOM。最后不得不手动注入样式,维护成本极高。

所以我的结论是:Web Components 适合做简单的跨框架组件,但不适合做完整的微前端方案

2.3 Module Federation:Webpack 5 的杀手锏

Module Federation 是 Webpack 5 推出的功能。它让多个独立构建的应用可以共享模块。

说白了,就是运行时加载远程代码

它的核心优势:

  • 真正的去中心化:每个应用都可以暴露自己的模块,也可以加载别人的模块
  • 共享依赖:可以配置共享的第三方库,避免重复加载
  • 性能优秀:基于 Webpack 的代码分割,按需加载
  • 类型安全:配合 TypeScript,可以做到编译时检查

举个例子,主应用可以这样加载远程组件:

// webpack.config.js (主应用)
new ModuleFederationPlugin({
  name: 'host',
  remotes: {
    app1: 'app1@http://localhost:3001/remoteEntry.js',
  },
})

// 在代码中使用
const RemoteButton = React.lazy(() => import('app1/Button'));

子应用暴露组件也很简单:

// webpack.config.js (子应用)
new ModuleFederationPlugin({
  name: 'app1',
  exposes: {
    './Button': './src/Button',
  },
})

但 Module Federation 也有坑:

  • 强依赖 Webpack 5:如果你用 Vite 或别的构建工具,需要额外插件
  • 配置复杂:shared、exposes、remotes 这些配置项很容易搞错
  • 版本冲突:共享依赖的版本不一致时,会出现奇怪的问题
  • 没有沙箱隔离:CSS 和 JS 的隔离需要自己处理

我的经验:

Module Federation 最适合的场景是同一个技术栈内的模块共享。比如多个 React 应用之间共享组件库、工具函数。如果你要做跨技术栈的微前端,它还需要配合其他方案使用。

2.4 single-spa:微前端的元老

single-spa 是微前端的鼻祖。它定义了一套生命周期规范,让不同框架的应用可以共存。

它的核心思想很简单:

  • 主应用负责路由分发
  • 子应用暴露生命周期函数(bootstrap、mount、unmount)
  • single-spa 根据路由切换,调用对应的生命周期

优点:

  • 框架无关:React、Vue、Angular、甚至 jQuery 都能接入
  • 轻量:核心库只有几十 KB
  • 成熟稳定:社区活跃,文档完善

缺点:

  • 没有样式隔离:CSS 需要自己处理
  • 没有 JS 沙箱:全局变量污染需要自己解决
  • 通信机制缺失:需要自己实现事件总线或状态管理
  • 子应用改造成本高:需要修改子应用的入口文件

一句话总结:

single-spa 是一个基础框架,它只解决了「如何加载和卸载子应用」的问题。样式隔离、JS 沙箱、通信这些,都需要你自己去实现。

2.5 qiankun:single-spa 的增强版

qiankun 是基于 single-spa 封装的。它解决了 single-spa 最让人头疼的几个问题。

qiankun 的核心增强:

  • JS 沙箱:基于 Proxy 实现,子应用之间的全局变量互不干扰
  • 样式隔离:支持 Shadow DOM 和实验性样式隔离方案
  • 预加载:可以在空闲时预加载子应用的资源
  • 开箱即用:接入成本比 single-spa 低很多

接入方式也很简单:

// 主应用
import { registerMicroApps, start } from 'qiankun';

registerMicroApps([
  {
    name: 'react-app',
    entry: '//localhost:3001',
    container: '#container',
    activeRule: '/react',
  },
]);

start();

但 qiankun 也不是银弹:

  • 沙箱性能开销:Proxy 沙箱在大量操作时会有性能损耗
  • 样式隔离不完美:实验性方案有兼容性问题,Shadow DOM 方案有局限性
  • 子应用改造依然存在:虽然比 single-spa 少,但还是需要改一些代码
  • 对老项目不友好:jQuery 项目接入 qiankun 经常出问题

避坑指南:

我曾经在一个项目中,子应用用了大量的 document.write 和 window.open。qiankun 的沙箱对这些操作的支持很差,最后不得不改子应用的代码。所以如果你要接入老项目,一定要先评估改造工作量。

2.6 横向对比:一张表说清楚

特性 iframe Web Components Module Federation single-spa qiankun
样式隔离 ✅ 完美 ✅ 完美 ❌ 无 ❌ 无 ⚠️ 有但有限
JS 隔离 ✅ 完美 ✅ 完美 ❌ 无 ❌ 无 ✅ 有
通信成本 ❌ 高 ⚠️ 中 ✅ 低 ⚠️ 中 ✅ 低
路由同步 ❌ 难 ⚠️ 需手动 ✅ 自然 ✅ 自然 ✅ 自然
性能 ⚠️ 中 ⚠️ 中 ✅ 高 ✅ 高 ⚠️ 中
接入成本 ✅ 极低 ⚠️ 中 ⚠️ 高 ⚠️ 中 ✅ 低
生态成熟度 ✅ 成熟 ❌ 不成熟 ⚠️ 发展中 ✅ 成熟 ✅ 成熟
跨技术栈 ✅ 支持 ✅ 支持 ⚠️ 有限 ✅ 支持 ✅ 支持

2.7 我的选型建议

说了这么多,到底怎么选?我给出几个场景化的建议:

  1. 临时集成第三方系统 → 选 iframe。别折腾,十分钟搞定。
  2. 同技术栈的模块共享 → 选 Module Federation。性能好,体验佳。
  3. 跨技术栈的新项目 → 选 qiankun。开箱即用,社区成熟。
  4. 对隔离性要求极高 → 选 iframe + qiankun 混合方案。核心模块用 iframe,普通模块用 qiankun。
  5. 团队有精力折腾 → 选 single-spa。自由度最高,但需要自己补全缺失的功能。
  6. Web Components → 暂时不建议用于微前端。等生态成熟了再说。

最后说一句:

没有完美的技术方案,只有最适合你的。选型的时候,多想想你的团队能力、项目现状、维护成本。别为了技术而技术。