微前端

一、是什么

微前端是将前端应用拆分为多个独立部署、独立运行、技术栈无关的子应用,由一个基座应用(容器)在运行时动态组合,形成完整前端体验。

类比后端:微服务 → 前端:微前端

二、为什么

场景说明
大型团队协作不同子应用由不同团队独立开发、测试、部署
多业务线系统CRM、ERP、BI 等系统集成在一个统一门户中
技术栈不统一老系统升级、不同团队技术偏好不同
增量迁移逐步将巨型 SPA 拆解或重构

三、实现方案

1. iframe(最简单)

  • ✅ 完全隔离:JS/CSS 互不影响
  • ✅ 原生支持,无侵入
  • ❌ 路由不同步(刷新/前进后退问题)
  • ❌ 通信困难(postMessage 繁琐)
  • ❌ 弹窗/全局遮罩无法跨 iframe
  • ❌ 性能开销大(每个 iframe 独立上下文)

适用:简单嵌入类场景(如运营活动页、第三方报表)

2. single-spa

import { registerApplication, start } from 'single-spa';

registerApplication({
  name: 'app1',
  app: () => import('app1/main.js'),
  activeWhen: ['/app1'],
});
start();
  • ✅ 路由级拆分

  • ✅ 多框架支持(React/Vue/Angular)

  • ❌ 需要自行解决:样式隔离、JS沙箱、公共依赖加载

3. Module Federation

// webpack.config.js
new ModuleFederationPlugin({
  name: 'host',
  remotes: {
    app2: 'app2@http://localhost:3002/remoteEntry.js',
  },
  shared: {
    react: { singleton: true, requiredVersion: '^18.0.0' },
  },
});
  • ✅ 运行时动态加载远程模块

  • ✅ 依赖共享(避免重复打包 React/Vue)

  • ✅ 支持模块级拆分(不只是应用级)

  • ❌ 配置复杂

  • ❌ 强依赖 Webpack(但已逐步被 Rspack 等兼容)

目前生产最常用的方案之一

4. qiankun (基于 single-spa)

import { registerMicroApps, start } from 'qiankun';

registerMicroApps([
  {
    name: 'app1',
    entry: '//localhost:3001',
    container: '#container',
    activeRule: '/app1',
  },
]);
start();
  • ✅ 开箱即用:JS沙箱(Proxy)、样式隔离(shadow DOM 或 scoped)

  • ✅ HTML Entry(自动加载 JS/CSS)

  • ✅ 阿里生产验证(蚂蚁、菜鸟等)

  • ❌ 对 Vite 支持较弱(需插件)

  • ❌ 依赖 single-spa 生态

5. 新兴方案(2024+)

方案特点
wujie(腾讯)基于 WebComponent + iframe 沙箱,更轻量
micro-app(京东)类 qiankun 但更轻,支持 Vite
无界支持 iframe 沙箱 + 路由同步

四、核心问题与解决方式

问题难点主流解法
子应用通信跨应用状态共享、事件传递① 基座事件总线(mitt / eventemitter)<br>② 全局状态管理(Redux / Zustand 挂载到 window)<br>③ 路由参数传递(简单场景)<br>④ 自定义浏览器事件(CustomEvent)
样式隔离CSS 规则相互污染、覆盖① CSS Modules / Scoped CSS(构建时隔离)<br>② Shadow DOM(qiankun 可选,强隔离)<br>③ BEM 命名约定 + 动态添加前缀<br>④ CSS-in-JS(运行时隔离)
JS 沙箱全局变量冲突、setTimeout/监听未清理、原型链污染Proxy 劫持 window(qiankun 沙箱)<br>② iframe 天然隔离(最强但最重)<br>③ 快照沙箱(降级方案,性能较差)<br>with + new Function 模拟作用域
路由同步子应用独立路由 + 主应用路由协同,刷新/前进后退保持状态主应用监听路由变化,通过 activeRule 激活子应用;子应用使用 memory 模式或继承基座路由(如 createWebHistory(base)
公共依赖加载多个子应用重复加载 React/Vue 等框架,首屏臃肿① Module Federation shared 配置共享<br>② externals + CDN 统一加载<br>③ 基座注入公共依赖(window.React
性能(首屏)主应用 + 多个子应用资源同时加载① 按需激活(路由懒加载)<br>② 子应用预加载(prefetch,用户 hover 菜单时)<br>③ 公共依赖强缓存<br>④ 子应用资源走 CDN
子应用生命周期子应用独立运行时 vs 被基座加载时的行为差异子应用导出 bootstrap / mount / unmount 生命周期;通过 window.__POWERED_BY_QIANKUN__ 等全局标志判断环境
构建产物兼容子应用打包出的 JS/CSS 可能污染全局或路径错误① 子应用配置 webpack publicPath 为动态(window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__<br>② 启用 asset 模块时设置 output.publicPath: 'auto'

通信详解示例(事件总线)

// 基座
import mitt from 'mitt';
window.microAppEventBus = mitt();

// 子应用 A 发送
window.microAppEventBus.emit('user-logout', { userId: 123 });

// 子应用 B 接收
window.microAppEventBus.on('user-logout', (data) => {
  console.log('清除本地缓存', data);
});

JS 沙箱简化原理(qiankun 实现思路)

class ProxySandbox {
  constructor() {
    const fakeWindow = Object.create(null);
    this.proxy = new Proxy(fakeWindow, {
      get: (target, prop) => target[prop] || window[prop],
      set: (target, prop, value) => {
        target[prop] = value;
        return true;
      },
    });
  }
}

五、最佳实践

1. 拆分粒度控制

  • 按业务域拆分:用户中心、订单中心、商品管理、支付中心
  • 按稳定度拆分:核心交易流程(稳定) vs 营销活动(频繁变更)
  • 按团队边界拆分:一个团队维护 1-2 个子应用
  • 不要按页面/组件过度拆分:增加通信和加载成本
  • 子应用数量建议 ≤ 20,过多则运维复杂、版本管理混乱

粒度判断标准

  • 能否独立部署且不影响其他子应用?
  • 是否有独立的业务价值?
  • 团队是否能独立决策其技术栈?

2. 统一基建(基座职责)

基座是微前端的"操作系统",统一提供以下能力,避免每个子应用重复造轮子

// 基座向子应用注入能力
if (window.__POWERED_BY_QIANKUN__) {
  window.__INJECTED_UTILS__ = {
    // 网络请求(统一 token、拦截器、错误处理)
    request: (url, options) =>
      fetch(url, { ...options, credentials: 'include' }),

    // 事件总线
    eventBus: window.microAppEventBus,

    // 用户信息
    getUser: () => window.__GLOBAL_USER__,

    // 权限校验
    hasPermission: (code) => window.__PERMISSIONS__.includes(code),

    // 埋点上报
    track: (eventName, data) => {
      /* 统一上报 */
    },

    // 全局通知
    notification: { success, error, warning },
  };
}

3. 与 Monorepo 的强绑定(工程化核心)

没有 Monorepo 的微前端,依赖管理和公共库升级会非常痛苦

目录结构示例:

monorepo/
  packages/
    base/              # 基座应用
    user-center/       # 用户中心子应用
    order/             # 订单子应用
    product/           # 商品子应用
    shared/            # 公共组件/工具/类型/常量
      src/
        components/    # Button、Modal 等
        utils/         # formatDate、deepClone
        hooks/         # useRequest、useAuth
        types/         # 全局 TS 类型
    config-eslint/      # 统一 ESLint 配置
    config-typescript/  # 统一 TS 配置
  package.json
  pnpm-workspace.yaml
  turbo.json