微前端

微前端是一种将前端应用拆分为多个小型、独立的前端应用的架构模式,每个应用可以独立开发、部署和维护。

1. 核心概念

1.1 什么是微前端

微前端的理念源于微服务,它将大型前端应用拆分为多个小型、自治的前端应用,每个应用负责特定的功能模块。

1.2 微前端的优势

  • 独立开发:每个团队可以独立开发自己的微前端应用
  • 独立部署:每个微前端应用可以独立部署,无需协调
  • 技术栈灵活:每个微前端应用可以使用不同的技术栈
  • 可扩展性:可以轻松添加或移除微前端应用
  • 故障隔离:一个微前端应用的故障不会影响其他应用

1.3 微前端的挑战

  • 通信问题:微前端应用之间需要有效的通信机制
  • 样式隔离:避免样式冲突
  • 状态管理:共享状态的管理
  • 路由协调:多个微前端应用的路由协调
  • 构建和部署复杂性:需要复杂的构建和部署流程

2. 微前端架构模式

2.1 基座模式

基座模式是最常见的微前端架构模式,它包含一个主应用(基座)和多个子应用(微前端)。

核心特点

  • 主应用:负责子应用的注册、加载和卸载
  • 子应用:独立开发和部署的前端应用
  • 通信方式:主应用和子应用之间通过事件或自定义API通信

实现示例

javascript
// 主应用注册子应用
import { registerApplication, start } from 'single-spa';

registerApplication(
  'app1',
  () => import('./src/app1/main.js'),
  location => location.pathname.startsWith('/app1'),
  { some: 'value' }
);

registerApplication(
  'app2',
  () => import('./src/app2/main.js'),
  location => location.pathname.startsWith('/app2')
);

start();

2.2 模块联邦

模块联邦是Webpack 5推出的新特性,允许不同的Webpack构建之间共享模块。

核心特点

  • 动态远程模块:可以动态加载远程模块
  • 无服务器依赖:不需要特殊的服务器支持
  • 简单配置:通过Webpack配置即可实现

实现示例

javascript
// 提供方配置 (webpack.config.js)
const { ModuleFederationPlugin } = require('webpack').container;

module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      name: 'app1',
      exposes: {
        './Button': './src/Button',
      },
      shared: ['react', 'react-dom'],
    }),
  ],
};
javascript
// 消费方配置 (webpack.config.js)
const { ModuleFederationPlugin } = require('webpack').container;

module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      name: 'app2',
      remotes: {
        app1: 'app1@http://localhost:3001/remoteEntry.js',
      },
      shared: ['react', 'react-dom'],
    }),
  ],
};
javascript
// 消费方使用远程模块
import { lazy, Suspense } from 'react';

const Button = lazy(() => import('app1/Button'));

function App() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <Button />
    </Suspense>
  );
}

3. 微前端框架

3.1 Single-SPA

Single-SPA是一个用于构建微前端应用的JavaScript框架,它允许在同一个页面中加载多个前端框架。

核心功能

  • 应用注册:注册和管理微前端应用
  • 路由协调:协调多个微前端应用的路由
  • 生命周期管理:管理微前端应用的加载、挂载和卸载
  • 通信机制:提供微前端应用之间的通信方式

快速开始

bash
# 安装Single-SPA CLI
npm install -g create-single-spa

# 创建Single-SPA应用
create-single-spa

3.2 Qiankun

Qiankun是一个基于Single-SPA的微前端框架,由蚂蚁金服开发,提供了更完善的功能和更好的开发体验。

核心功能

  • HTML Entry:支持通过HTML入口加载微前端应用
  • 样式隔离:自动处理样式隔离
  • JS沙箱:提供JavaScript沙箱环境
  • 预加载:支持预加载微前端应用
  • 简单API:提供简洁易用的API

快速开始

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

registerMicroApps([
  {
    name: 'app1',
    entry: '//localhost:8080',
    container: '#container',
    activeRule: '/app1',
  },
  {
    name: 'app2',
    entry: '//localhost:8081',
    container: '#container',
    activeRule: '/app2',
  },
]);

start();
javascript
// 子应用配置 (main.js)
export async function bootstrap() {
  console.log('app1 bootstraped');
}

export async function mount(props) {
  console.log('app1 mounted', props);
  // 渲染应用
}

export async function unmount(props) {
  console.log('app1 unmounted', props);
  // 卸载应用
}

3.3 Piral

Piral是一个微前端框架,专注于构建可扩展的Web应用程序。

核心功能

  • 插件系统:基于插件的微前端架构
  • 中央状态管理:提供中央状态管理
  • 路由管理:内置路由管理
  • 组件共享:支持组件共享
  • 开发工具:提供丰富的开发工具

4. 微前端通信

4.1 基于事件的通信

基于事件的通信是一种松耦合的通信方式,通过发布-订阅模式实现。

javascript
// 事件总线
class EventBus {
  constructor() {
    this.events = {};
  }

  on(event, callback) {
    if (!this.events[event]) {
      this.events[event] = [];
    }
    this.events[event].push(callback);
  }

  emit(event, data) {
    if (this.events[event]) {
      this.events[event].forEach(callback => {
        callback(data);
      });
    }
  }

  off(event, callback) {
    if (this.events[event]) {
      this.events[event] = this.events[event].filter(cb => cb !== callback);
    }
  }
}

// 使用事件总线
const eventBus = new EventBus();

// 订阅事件
eventBus.on('userLoggedIn', (user) => {
  console.log('User logged in:', user);
});

// 发布事件
eventBus.emit('userLoggedIn', { id: 1, name: 'Alice' });

4.2 基于props的通信

基于props的通信是主应用向子应用传递数据的简单方式。

javascript
// 主应用
registerApplication(
  'app1',
  () => import('./src/app1/main.js'),
  location => location.pathname.startsWith('/app1'),
  { user: { id: 1, name: 'Alice' } }
);

// 子应用
export async function mount(props) {
  console.log('User prop:', props.user);
}

4.3 基于自定义API的通信

基于自定义API的通信是一种更结构化的通信方式,提供明确的API接口。

javascript
// 主应用提供API
const sharedApi = {
  getUser: () => ({ id: 1, name: 'Alice' }),
  setUser: (user) => { /* 设置用户 */ }
};

registerApplication(
  'app1',
  () => import('./src/app1/main.js'),
  location => location.pathname.startsWith('/app1'),
  { api: sharedApi }
);

5. 样式隔离

5.1 CSS Modules

CSS Modules通过生成唯一的类名来避免样式冲突。

css
/* Button.module.css */
.button {
  background-color: blue;
  color: white;
  padding: 8px 16px;
}
javascript
import styles from './Button.module.css';

function Button() {
  return <button className={styles.button}>Click me</button>;
}

5.2 Shadow DOM

Shadow DOM提供了DOM和样式的隔离。

javascript
class ShadowButton extends HTMLElement {
  constructor() {
    super();
    const shadowRoot = this.attachShadow({ mode: 'open' });
    shadowRoot.innerHTML = `
      <style>
        button {
          background-color: blue;
          color: white;
          padding: 8px 16px;
        }
      </style>
      <button><slot></slot></button>
    `;
  }
}

customElements.define('shadow-button', ShadowButton);

5.3 CSS-in-JS

CSS-in-JS通过JavaScript动态生成样式,避免样式冲突。

javascript
import styled from 'styled-components';

const Button = styled.button`
  background-color: blue;
  color: white;
  padding: 8px 16px;
`;

function App() {
  return <Button>Click me</Button>;
}

6. 微前端路由

6.1 基于路径的路由

基于路径的路由是最常见的微前端路由方式,根据URL路径加载对应的微前端应用。

javascript
registerApplication(
  'app1',
  () => import('./src/app1/main.js'),
  location => location.pathname.startsWith('/app1')
);

6.2 基于子域名的路由

基于子域名的路由根据子域名加载对应的微前端应用。

javascript
registerApplication(
  'app1',
  () => import('./src/app1/main.js'),
  location => location.hostname === 'app1.example.com'
);

6.3 基于路由库的路由

使用专门的路由库来管理微前端应用的路由。

javascript
// 使用React Router
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import App1 from './App1';
import App2 from './App2';

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/app1/*" element={<App1 />} />
        <Route path="/app2/*" element={<App2 />} />
      </Routes>
    </BrowserRouter>
  );
}

7. 微前端最佳实践

7.1 独立开发和部署

每个微前端应用应该有自己的代码库、构建流程和部署流程。

7.2 明确定义边界

每个微前端应用应该有明确的功能边界,避免功能重叠。

7.3 使用统一的设计系统

使用统一的设计系统确保微前端应用之间的视觉一致性。

7.4 保持技术栈的多样性

允许每个微前端应用使用最适合的技术栈,但也要考虑维护成本。

7.5 实现有效的监控

实现有效的监控系统,及时发现和解决问题。

8. 微前端案例

8.1 Spotify

Spotify使用微前端架构构建其Web应用,每个功能模块由不同的团队独立开发和部署。

8.2 IKEA

IKEA使用微前端架构构建其电子商务平台,提高了开发效率和可扩展性。

8.3 Zalando

Zalando使用微前端架构构建其时尚电商平台,支持多个团队并行开发。

学习资源

最后更新:2026-02-08