为什么需要微前端
单体前端项目到了一定规模就会陷入泥潭:代码库越来越大,构建越来越慢,团队并行开发互相踩线,发版要全量回归。微前端把大前端拆成多个独立开发、独立部署的子应用,由一个主应用负责壳与路由,子应用按需加载,从架构上解耦团队与发布。
微前端的本质是"运行时组合":多个子应用的代码在浏览器里被主应用组织成一个完整产品。它与后端微服务的对应关系并不严格——子应用可以是独立技术栈、独立仓库、独立发布节奏,但共享同一套用户体系与导航壳。
- 主应用负责壳、路由与子应用调度。
- 子应用独立开发部署,按需挂载。
- qiankun基于 single-spa 的成熟方案。
- 模块联邦Webpack 5 的运行时共享。
微前端三大技术路线
实现微前端有三条主流路线。iframe 最简单:天然隔离样式与脚本,但通信麻烦、体验割裂、弹窗定位与滚动都有历史包袱,适合隔离要求极高的小场景,不适合做核心产品壳。single-spa 是通用微前端框架,管理子应用的注册与生命周期,但样式隔离、通信等都要自己补。
qiankun 是蚂蚁开源的单体框架,基于 single-spa 加 HTML Entry、样式隔离、沙箱与资源预加载,开箱即用,是国内微前端事实标准。模块联邦则是 Webpack 5 的内置能力,构建期声明共享依赖,运行时从一个远程模块图里拉取组件,适合同技术栈团队的组件级共享。
qiankun 主应用接入
主应用用 registerMicroApps 注册子应用:配置 name、entry、container 与 activeRule,路由命中 activeRule 时把子应用挂载到指定容器。用 start 启动,prefetch 默认开启会预拉子应用资源。
import { registerMicroApps, start } from "qiankun";
registerMicroApps([
{
name: "order",
entry: "//order.example.com",
container: "#subapp-container",
activeRule: "/order",
},
{
name: "user",
entry: "//user.example.com",
container: "#subapp-container",
activeRule: "/user",
},
]);
start({ prefetch: true });
主应用的基座里,导航与用户态要设计成全局能力:子应用通过主应用暴露的全局对象拿用户信息、跳转路由、打开弹窗。基座的稳定性直接影响全部子应用,主应用要小、要稳,尽量不随业务迭代大改。
子应用接入与生命周期
子应用要导出生命周期钩子:bootstrap 初始化一次,mount 挂载渲染,unmount 卸载清理。qiankun 通过 HTML Entry 加载子应用的 HTML,自动执行其中的脚本,子应用要暴露这些钩子并配置 publicPath 支持运行时设置资源路径。
// 子应用 main.js 示例(Vue)
let instance;
export async function bootstrap() {}
export async function mount(props) {
instance = new Vue({ router, render: h => h(App) }).$mount("#app");
}
export async function unmount() {
instance.$destroy();
instance.$el.innerHTML = "";
}
生命周期最容易踩的坑:unmount 只销毁框架实例不清理副作用,事件监听与全局定时器泄漏,导致子应用反复挂载后内存上涨、事件重复触发。规范是把所有副作用登记在 unmount 里成对清理。
样式隔离与通信
qiankun 默认开启样式隔离,会把子应用的样式限定在容器作用域内;还要约定团队规范:子应用全局样式只写业务不写 reset,组件库样式通过 scoped 或 CSS Modules 处理,避免互相污染。CSS 变量可以作为跨应用的样式契约。
子应用间通信不要用全局变量满天飞。qiankun 提供 props 下发:主应用通过 mount 的 props 传全局状态与 API;复杂场景用全局事件总线或状态管理库,事件名统一命名空间;跨应用调接口统一走主应用暴露的服务,别让子应用直连各自后端,否则用户体系与鉴权会乱。
// 主应用向子应用下发全局能力
start({
sandbox: { strictStyleIsolation: true },
global: { userInfo, navigate, openModal }
});
部署与构建
子应用独立部署是微前端的核心收益:每个子应用有自己的仓库、流水线与发布窗口。部署架构上,主应用与各子应用部署到不同路径或不同域名,主应用通过子应用的入口 URL 加载;CDN 上按版本目录管理资源,支持灰度与回滚。
构建上要注意几点:子应用的 publicPath 要用运行时变量,避免写死导致资源 404;公共依赖尽量抽到运行时共享或体积可接受就各自打包;子应用按需拆包,不要一个应用全量打包让首屏变慢;主应用与子应用之间的路由前缀约定清楚,避免冲突。
// webpack 子应用配置要点
output: {
library: { type: "umd", name: "orderApp" },
publicPath: "auto", // 运行时动态资源路径
jsonpFunction: "webpackJsonp_order",
}
落地清单
微前端不是银弹,落地前先确认动机:是为了团队独立与发布解耦,还是为了技术栈演进。如果只是页面多,单体加路由拆包可能更省事。决定上微前端后,按顺序推进:先定主应用壳与全局能力;挑一个低风险业务做第一个子应用跑通全链路;再逐步迁移其余模块,每次只切一个。
工程规范要同步立起来:子应用生命周期与副作用清理写进模板;样式隔离与通信约定写进文档;部署脚本统一带版本与回滚;监控覆盖子应用加载成功率与首屏性能。微前端的成功标准不是"切了多少模块",而是"团队可以独立发版且事故率不上升"。
- 先确认动机,非必要不微前端。
- 主应用保持小而稳,全局能力清晰。
- 子应用副作用成对清理,防泄漏。
- 部署带版本与回滚,监控加载成功率。