“微前端(Micro Frontends)” 是将大型前端应用拆分成多个独立开发、独立部署的小型应用,每个小应用负责一部分功能,多个前端团队可以并行开发、独立发布各自的子应用,最终整合在一个主应用中统一呈现。
这个理念是借鉴“微服务”在后端的思想,但应用于前端架构。
微前端核心理念
- 独立性: 每个子应用可以独立开发、构建、部署
- 技术栈无关: 不同子应用可以用 React/Vue/Angular 等不同框架
- 主应用统一管理路由/UI: 主应用负责页面路由分发和整体布局
- 运行时集成: 子应用在运行时动态加载(而不是构建时打包在一起)
典型使用场景
- 多团队协同开发大型前端系统(如电商后台、CMS、SaaS平台)
- 系统模块更新频繁,部署希望低耦合
- 需要支持不同技术栈或版本共存
优点(不使用微前端)
- 开发简单:不需要拆分子应用,不用考虑通信、隔离等复杂问题
- 构建部署流程统一:一次构建,一次部署,流程清晰
- 调试方便:不存在跨子应用跳转或版本冲突问题
- 性能更好(初期):无需动态加载多个子应用资源,初始加载更快
- 技术栈统一:不存在多个框架共存问题(如 React + Vue)
缺点(当项目变大时)
- 团队协作冲突大:多团队同时改动一个项目,易冲突,CI/CD难以并行
- 构建时间越来越长:代码体积庞大,构建几分钟起步
- 更新粒度粗:改一个小功能也要重新构建整个项目并全量上线
- 技术升级困难:想把 Vue2 升级到 Vue3,牵一发动全身
- 难以复用已有系统模块:多系统难以共享模块或 UI
微前端技术方案
| 方案 | 简介 | 优点 | 缺点 |
|---|---|---|---|
| Qiankun | 基于 Single-SPA,阿里出品的微前端框架 | 成熟、支持多框架、文档完善 | 框架较重,子应用需适配 |
| Single-SPA | 最早的微前端框架之一 | 灵活、社区强 | 上手略复杂 |
| Module Federation(Webpack 5) | 原生支持模块共享 | 轻量、适合模块共享 | 需要 Webpack 5 |
| iframe | 每个子应用放在 iframe 中 | 完全隔离、简单实现 | 用户体验差、通信麻烦 |
为什么不用iframe
1. 先说优点(为什么很多人会想到 iframe)
- 天然隔离:iframe 天然能隔离 CSS、JS 作用域,避免子应用相互污染。
- 安全性:不同应用在独立的渲染上下文运行,跨站安全问题更容易控制。
- 上手简单:直接 <iframe src="xxx"> 就能加载一个子应用。
2. iframe 的缺点(导致不被推荐)
- 用户体验差
- 每个子应用都是独立文档,页面切换会闪烁、白屏。
- iframe 内的内容无法自然适配父应用的 滚动、布局。
- 路由与刷新问题
- iframe 有独立的路由体系,无法和浏览器地址栏同步,不利于前端路由统一管理(例如刷新、前进、后退行为会失效)。
- 跨应用通信困难
- 父子应用通信要靠 postMessage,相比于 JS 沙箱、共享事件总线等机制,不够灵活高效。
- SEO 不友好
- 搜索引擎对 iframe 内容抓取有限,不利于 SEO。
- 样式和交互割裂
- 子应用和主应用之间的样式、弹窗、全局快捷键、右键菜单等都无法无缝衔接,用户体验不一致。
- 性能问题
- iframe 会占用较多资源,每个子应用都要单独创建浏览器上下文,内存和加载性能差。
基于 JS 沙箱的微前端隔离方案
JS 沙箱的目标:
👉 在同一个页面里运行多个子应用,但互不干扰。
1. Proxy 代理 window
- 通过 ES6 Proxy 拦截子应用对 window 的读写操作;
- 每个子应用获得一个“假的 window”(proxy 对象),只在自己的作用域生效;
例如:
const fakeWindow = new Proxy(window, { get(target, key) { return target[key]; }, set(target, key, value) { // 只修改沙箱环境,不污染真实 window targetSandbox[key] = value; return true; } });- 子应用执行 window.a = 1,只会存在于自己的沙箱,不会污染主应用或其他子应用。
2. with + eval 改变执行上下文
- 通过 with (proxy) { eval(code) } 的方式,强制子应用代码在 proxy 环境下运行;
- 这样,子应用里的所有变量查找,都会优先从 sandbox(Proxy)里取。
3. 生命周期控制
- qiankun 在子应用 mount/unmount 时,会:
- 激活沙箱(打开 Proxy 代理);
- 清理子应用注册的全局变量和副作用(如定时器、事件监听)。
4. 样式隔离(配合 Shadow DOM 或样式前缀)
- JS 沙箱解决的是 全局对象污染;
- CSS 冲突 qiankun 会通过 动态样式隔离 解决,比如:
- scoped css / Shadow DOM
- 或运行时给子应用样式加上前缀。