发布于

微前端架构实战:Module Federation与单页应用拆分策略

作者

微前端架构实战:Module Federation与单页应用拆分策略

微前端架构允许多个团队独立开发、部署和维护前端应用的不同部分。本文将分享微前端架构的设计理念和实战经验。

微前端基础概念

架构设计原则

// 微前端架构设计原则
const MicroFrontendPrinciples = {
  // 1. 技术栈无关性
  technologyAgnostic: {
    description: '不同微应用可以使用不同的技术栈',
    examples: ['React + Webpack', 'Vue + Vite', 'Angular + CLI'],
    benefits: ['团队自主选择', '技术栈升级独立', '人才利用最大化']
  },
  
  // 2. 独立部署
  independentDeployment: {
    description: '每个微应用可以独立构建和部署',
    requirements: ['独立的CI/CD流水线', '版本管理策略', '回滚机制'],
    benefits: ['降低部署风险', '提高发布频率', '减少团队依赖']
  },
  
  // 3. 团队自治
  teamAutonomy: {
    description: '每个团队负责完整的业务功能',
    includes: ['前端开发', '后端API', '数据库设计', '测试部署'],
    benefits: ['责任明确', '决策快速', '技术债务可控']
  },
  
  // 4. 渐进式升级
  incrementalUpgrade: {
    description: '支持逐步迁移和升级',
    strategies: ['路由级拆分', '组件级拆分', '功能模块拆分'],
    benefits: ['降低迁移风险', '平滑过渡', '业务连续性']
  }
};

// 微前端架构模式
const ArchitecturePatterns = {
  // 1. 路由分发模式
  routeDistribution: {
    description: '基于路由将不同页面分配给不同微应用',
    implementation: 'nginx配置或网关路由',
    pros: ['简单易实现', '完全隔离', '技术栈自由'],
    cons: ['页面跳转刷新', '状态难共享', '用户体验割裂']
  },
  
  // 2. 主从模式
  masterSlave: {
    description: '主应用负责路由和公共功能,子应用负责业务功能',
    implementation: 'single-spa、qiankun等框架',
    pros: ['SPA体验', '状态可共享', '公共资源复用'],
    cons: ['主应用复杂', '技术栈限制', '版本依赖']
  },
  
  // 3. 自组织模式
  selfOrganizing: {
    description: '微应用之间通过事件总线或消息机制协调',
    implementation: '事件驱动架构',
    pros: ['松耦合', '扩展性强', '故障隔离'],
    cons: ['复杂度高', '调试困难', '性能开销']
  },
  
  // 4. 微件模式
  widget: {
    description: '将微应用作为可嵌入的组件使用',
    implementation: 'Web Components或iframe',
    pros: ['复用性强', '隔离性好', '集成简单'],
    cons: ['通信复杂', '样式隔离', '性能损耗']
  }
};

技术选型对比

// 微前端技术方案对比
const TechnicalSolutions = {
  // 1. iframe方案
  iframe: {
    advantages: [
      '完全隔离(样式、JS、全局变量)',
      '技术栈无关',
      '实现简单',
      '安全性高'
    ],
    disadvantages: [
      '用户体验差(刷新、前进后退)',
      '通信复杂',
      '性能开销大',
      'SEO不友好',
      '移动端兼容性问题'
    ],
    useCase: '第三方应用集成、安全要求高的场景',
    implementation: `
      // iframe集成示例
      class IframeMicroApp {
        constructor(container, url) {
          this.container = container;
          this.url = url;
          this.iframe = null;
        }
        
        mount() {
          this.iframe = document.createElement('iframe');
          this.iframe.src = this.url;
          this.iframe.style.cssText = 'width: 100%; height: 100%; border: none;';
          this.container.appendChild(this.iframe);
          
          // 监听iframe消息
          window.addEventListener('message', this.handleMessage.bind(this));
        }
        
        unmount() {
          if (this.iframe) {
            this.container.removeChild(this.iframe);
            this.iframe = null;
          }
          window.removeEventListener('message', this.handleMessage);
        }
        
        handleMessage(event) {
          if (event.source === this.iframe.contentWindow) {
            // 处理来自iframe的消息
            console.log('Message from iframe:', event.data);
          }
        }
        
        sendMessage(data) {
          if (this.iframe) {
            this.iframe.contentWindow.postMessage(data, '*');
          }
        }
      }
    `
  },
  
  // 2. Web Components方案
  webComponents: {
    advantages: [
      '原生浏览器支持',
      '样式隔离(Shadow DOM)',
      '技术栈无关',
      '标准化API',
      '可复用性强'
    ],
    disadvantages: [
      '浏览器兼容性',
      '开发复杂度高',
      '调试困难',
      '生态不够成熟'
    ],
    useCase: '组件级微前端、跨框架组件复用',
    implementation: `
      // Web Components微应用
      class MicroAppElement extends HTMLElement {
        constructor() {
          super();
          this.attachShadow({ mode: 'open' });
        }
        
        connectedCallback() {
          this.render();
          this.loadMicroApp();
        }
        
        render() {
          this.shadowRoot.innerHTML = \`
            <style>
              :host {
                display: block;
                width: 100%;
                height: 100%;
              }
              .container {
                width: 100%;
                height: 100%;
              }
            </style>
            <div class="container" id="micro-app-container"></div>
          \`;
        }
        
        async loadMicroApp() {
          const appUrl = this.getAttribute('app-url');
          const container = this.shadowRoot.getElementById('micro-app-container');
          
          // 动态加载微应用
          const module = await import(appUrl);
          module.default.mount(container);
        }
      }
      
      customElements.define('micro-app', MicroAppElement);
    `
  },
  
  // 3. JavaScript沙箱方案
  jsSandbox: {
    advantages: [
      'SPA用户体验',
      '资源共享',
      '通信便捷',
      '性能较好'
    ],
    disadvantages: [
      '样式隔离复杂',
      '全局变量污染',
      '技术栈有限制',
      '实现复杂'
    ],
    useCase: '同技术栈微前端、企业内部应用',
    implementation: `
      // JavaScript沙箱实现
      class JavaScriptSandbox {
        constructor() {
          this.proxyWindow = null;
          this.originalWindow = window;
          this.modifiedProps = new Map();
        }
        
        createSandbox() {
          const fakeWindow = Object.create(null);
          
          this.proxyWindow = new Proxy(fakeWindow, {
            get: (target, prop) => {
              if (prop in target) {
                return target[prop];
              }
              
              const value = this.originalWindow[prop];
              if (typeof value === 'function') {
                return value.bind(this.originalWindow);
              }
              
              return value;
            },
            
            set: (target, prop, value) => {
              if (!this.modifiedProps.has(prop)) {
                this.modifiedProps.set(prop, this.originalWindow[prop]);
              }
              
              target[prop] = value;
              this.originalWindow[prop] = value;
              return true;
            }
          });
          
          return this.proxyWindow;
        }
        
        destroy() {
          // 恢复被修改的全局变量
          this.modifiedProps.forEach((originalValue, prop) => {
            if (originalValue === undefined) {
              delete this.originalWindow[prop];
            } else {
              this.originalWindow[prop] = originalValue;
            }
          });
          
          this.modifiedProps.clear();
          this.proxyWindow = null;
        }
      }
    `
  }
};

Module Federation实战

Webpack Module Federation配置

// webpack.config.js - 主应用配置
const ModuleFederationPlugin = require('@module-federation/webpack');

module.exports = {
  mode: 'development',
  devServer: {
    port: 3000,
    historyApiFallback: true,
  },
  
  plugins: [
    new ModuleFederationPlugin({
      name: 'shell', // 主应用名称
      remotes: {
        // 远程微应用配置
        'user-app': 'userApp@http://localhost:3001/remoteEntry.js',
        'product-app': 'productApp@http://localhost:3002/remoteEntry.js',
        'order-app': 'orderApp@http://localhost:3003/remoteEntry.js',
      },
      shared: {
        // 共享依赖配置
        react: {
          singleton: true,
          requiredVersion: '^18.0.0',
          eager: true,
        },
        'react-dom': {
          singleton: true,
          requiredVersion: '^18.0.0',
          eager: true,
        },
        'react-router-dom': {
          singleton: true,
          requiredVersion: '^6.0.0',
        },
        antd: {
          singleton: true,
          requiredVersion: '^5.0.0',
        },
        axios: {
          singleton: true,
          requiredVersion: '^1.0.0',
        },
      },
    }),
  ],
};

// webpack.config.js - 微应用配置(用户管理应用)
module.exports = {
  mode: 'development',
  devServer: {
    port: 3001,
    historyApiFallback: true,
    headers: {
      'Access-Control-Allow-Origin': '*',
    },
  },
  
  plugins: [
    new ModuleFederationPlugin({
      name: 'userApp',
      filename: 'remoteEntry.js',
      exposes: {
        // 暴露的模块
        './UserApp': './src/App',
        './UserList': './src/components/UserList',
        './UserForm': './src/components/UserForm',
        './userService': './src/services/userService',
      },
      shared: {
        react: {
          singleton: true,
          requiredVersion: '^18.0.0',
        },
        'react-dom': {
          singleton: true,
          requiredVersion: '^18.0.0',
        },
        'react-router-dom': {
          singleton: true,
          requiredVersion: '^6.0.0',
        },
        antd: {
          singleton: true,
          requiredVersion: '^5.0.0',
        },
      },
    }),
  ],
};

// 主应用路由配置
import React, { Suspense } from 'react';
import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom';
import { Layout, Menu, Spin } from 'antd';
import ErrorBoundary from './components/ErrorBoundary';

// 动态导入微应用
const UserApp = React.lazy(() => import('user-app/UserApp'));
const ProductApp = React.lazy(() => import('product-app/ProductApp'));
const OrderApp = React.lazy(() => import('order-app/OrderApp'));

const { Header, Sider, Content } = Layout;

function App() {
  const menuItems = [
    {
      key: 'users',
      label: '用户管理',
      path: '/users',
    },
    {
      key: 'products',
      label: '产品管理',
      path: '/products',
    },
    {
      key: 'orders',
      label: '订单管理',
      path: '/orders',
    },
  ];

  return (
    <Router>
      <Layout style={{ minHeight: '100vh' }}>
        <Header>
          <div style={{ color: 'white', fontSize: '18px' }}>
            微前端管理系统
          </div>
        </Header>
        
        <Layout>
          <Sider width={200}>
            <Menu
              mode="inline"
              defaultSelectedKeys={['users']}
              items={menuItems.map(item => ({
                key: item.key,
                label: (
                  <a href={item.path}>{item.label}</a>
                ),
              }))}
            />
          </Sider>
          
          <Layout>
            <Content style={{ padding: '24px' }}>
              <ErrorBoundary>
                <Suspense fallback={<Spin size="large" />}>
                  <Routes>
                    <Route path="/" element={<Navigate to="/users" replace />} />
                    <Route path="/users/*" element={<UserApp />} />
                    <Route path="/products/*" element={<ProductApp />} />
                    <Route path="/orders/*" element={<OrderApp />} />
                  </Routes>
                </Suspense>
              </ErrorBoundary>
            </Content>
          </Layout>
        </Layout>
      </Layout>
    </Router>
  );
}

export default App;

微应用开发模式

// 微应用入口文件 - src/bootstrap.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import App from './App';

// 微应用生命周期管理
class MicroAppLifecycle {
  constructor() {
    this.root = null;
    this.container = null;
  }
  
  // 挂载应用
  mount(container, props = {}) {
    this.container = container;
    
    const MicroApp = () => (
      <BrowserRouter basename={props.basename || '/users'}>
        <App {...props} />
      </BrowserRouter>
    );
    
    this.root = ReactDOM.createRoot(container);
    this.root.render(<MicroApp />);
    
    console.log('User app mounted');
  }
  
  // 卸载应用
  unmount() {
    if (this.root) {
      this.root.unmount();
      this.root = null;
    }
    
    if (this.container) {
      this.container.innerHTML = '';
      this.container = null;
    }
    
    console.log('User app unmounted');
  }
  
  // 更新应用
  update(props) {
    if (this.root) {
      const MicroApp = () => (
        <BrowserRouter basename={props.basename || '/users'}>
          <App {...props} />
        </BrowserRouter>
      );
      
      this.root.render(<MicroApp />);
    }
  }
}

// 创建生命周期实例
const lifecycle = new MicroAppLifecycle();

// 独立运行模式
if (!window.__POWERED_BY_QIANKUN__) {
  const container = document.getElementById('root');
  if (container) {
    lifecycle.mount(container);
  }
}

// 导出生命周期钩子(兼容qiankun)
export async function mount(props) {
  lifecycle.mount(props.container, props);
}

export async function unmount(props) {
  lifecycle.unmount();
}

export async function update(props) {
  lifecycle.update(props);
}

// 导出应用实例(Module Federation)
export default {
  mount: lifecycle.mount.bind(lifecycle),
  unmount: lifecycle.unmount.bind(lifecycle),
  update: lifecycle.update.bind(lifecycle),
};

// 微应用主组件 - src/App.js
import React from 'react';
import { Routes, Route, Navigate } from 'react-router-dom';
import { ConfigProvider } from 'antd';
import zhCN from 'antd/locale/zh_CN';
import UserList from './components/UserList';
import UserDetail from './components/UserDetail';
import UserForm from './components/UserForm';
import { UserProvider } from './contexts/UserContext';

function App(props) {
  return (
    <ConfigProvider locale={zhCN}>
      <UserProvider>
        <div className="user-app">
          <Routes>
            <Route path="/" element={<Navigate to="/list" replace />} />
            <Route path="/list" element={<UserList />} />
            <Route path="/detail/:id" element={<UserDetail />} />
            <Route path="/create" element={<UserForm />} />
            <Route path="/edit/:id" element={<UserForm />} />
          </Routes>
        </div>
      </UserProvider>
    </ConfigProvider>
  );
}

export default App;

// 用户上下文 - src/contexts/UserContext.js
import React, { createContext, useContext, useReducer } from 'react';
import { userService } from '../services/userService';

const UserContext = createContext();

const initialState = {
  users: [],
  loading: false,
  error: null,
  selectedUser: null,
};

function userReducer(state, action) {
  switch (action.type) {
    case 'SET_LOADING':
      return { ...state, loading: action.payload };
    
    case 'SET_USERS':
      return { ...state, users: action.payload, loading: false };
    
    case 'SET_ERROR':
      return { ...state, error: action.payload, loading: false };
    
    case 'ADD_USER':
      return { ...state, users: [...state.users, action.payload] };
    
    case 'UPDATE_USER':
      return {
        ...state,
        users: state.users.map(user =>
          user.id === action.payload.id ? action.payload : user
        ),
      };
    
    case 'DELETE_USER':
      return {
        ...state,
        users: state.users.filter(user => user.id !== action.payload),
      };
    
    case 'SET_SELECTED_USER':
      return { ...state, selectedUser: action.payload };
    
    default:
      return state;
  }
}

export function UserProvider({ children }) {
  const [state, dispatch] = useReducer(userReducer, initialState);
  
  const actions = {
    async fetchUsers() {
      dispatch({ type: 'SET_LOADING', payload: true });
      try {
        const users = await userService.getUsers();
        dispatch({ type: 'SET_USERS', payload: users });
      } catch (error) {
        dispatch({ type: 'SET_ERROR', payload: error.message });
      }
    },
    
    async createUser(userData) {
      try {
        const newUser = await userService.createUser(userData);
        dispatch({ type: 'ADD_USER', payload: newUser });
        return newUser;
      } catch (error) {
        dispatch({ type: 'SET_ERROR', payload: error.message });
        throw error;
      }
    },
    
    async updateUser(id, userData) {
      try {
        const updatedUser = await userService.updateUser(id, userData);
        dispatch({ type: 'UPDATE_USER', payload: updatedUser });
        return updatedUser;
      } catch (error) {
        dispatch({ type: 'SET_ERROR', payload: error.message });
        throw error;
      }
    },
    
    async deleteUser(id) {
      try {
        await userService.deleteUser(id);
        dispatch({ type: 'DELETE_USER', payload: id });
      } catch (error) {
        dispatch({ type: 'SET_ERROR', payload: error.message });
        throw error;
      }
    },
    
    setSelectedUser(user) {
      dispatch({ type: 'SET_SELECTED_USER', payload: user });
    },
  };
  
  return (
    <UserContext.Provider value={{ state, actions }}>
      {children}
    </UserContext.Provider>
  );
}

export function useUser() {
  const context = useContext(UserContext);
  if (!context) {
    throw new Error('useUser must be used within a UserProvider');
  }
  return context;
}

应用间通信机制

// 微前端通信管理器
class MicroFrontendCommunication {
  constructor() {
    this.eventBus = new EventTarget();
    this.sharedStore = new Map();
    this.subscribers = new Map();
  }
  
  // 事件通信
  emit(eventName, data) {
    const event = new CustomEvent(eventName, { detail: data });
    this.eventBus.dispatchEvent(event);
    
    console.log(`Event emitted: ${eventName}`, data);
  }
  
  on(eventName, callback) {
    this.eventBus.addEventListener(eventName, callback);
    
    // 记录订阅者
    if (!this.subscribers.has(eventName)) {
      this.subscribers.set(eventName, new Set());
    }
    this.subscribers.get(eventName).add(callback);
  }
  
  off(eventName, callback) {
    this.eventBus.removeEventListener(eventName, callback);
    
    // 移除订阅者记录
    if (this.subscribers.has(eventName)) {
      this.subscribers.get(eventName).delete(callback);
    }
  }
  
  // 共享状态管理
  setState(key, value) {
    const oldValue = this.sharedStore.get(key);
    this.sharedStore.set(key, value);
    
    // 触发状态变更事件
    this.emit('state-changed', {
      key,
      value,
      oldValue,
      timestamp: Date.now(),
    });
  }
  
  getState(key) {
    return this.sharedStore.get(key);
  }
  
  getAllState() {
    return Object.fromEntries(this.sharedStore);
  }
  
  // 订阅状态变化
  onStateChange(key, callback) {
    const handler = (event) => {
      if (event.detail.key === key) {
        callback(event.detail.value, event.detail.oldValue);
      }
    };
    
    this.on('state-changed', handler);
    return () => this.off('state-changed', handler);
  }
  
  // 应用间方法调用
  registerMethod(methodName, method) {
    this.sharedStore.set(`method:${methodName}`, method);
  }
  
  callMethod(methodName, ...args) {
    const method = this.sharedStore.get(`method:${methodName}`);
    if (typeof method === 'function') {
      return method(...args);
    }
    throw new Error(`Method ${methodName} not found`);
  }
  
  // 路由通信
  navigateTo(path, state = {}) {
    this.emit('navigate', { path, state });
  }
  
  onNavigate(callback) {
    this.on('navigate', callback);
  }
  
  // 用户信息共享
  setUser(userInfo) {
    this.setState('currentUser', userInfo);
    this.emit('user-changed', userInfo);
  }
  
  getUser() {
    return this.getState('currentUser');
  }
  
  onUserChange(callback) {
    this.on('user-changed', callback);
  }
  
  // 权限信息共享
  setPermissions(permissions) {
    this.setState('permissions', permissions);
    this.emit('permissions-changed', permissions);
  }
  
  getPermissions() {
    return this.getState('permissions') || [];
  }
  
  hasPermission(permission) {
    const permissions = this.getPermissions();
    return permissions.includes(permission);
  }
  
  // 主题配置共享
  setTheme(theme) {
    this.setState('theme', theme);
    this.emit('theme-changed', theme);
    
    // 应用主题到DOM
    document.documentElement.setAttribute('data-theme', theme);
  }
  
  getTheme() {
    return this.getState('theme') || 'light';
  }
  
  onThemeChange(callback) {
    this.on('theme-changed', callback);
  }
  
  // 全局加载状态
  setGlobalLoading(loading) {
    this.setState('globalLoading', loading);
    this.emit('global-loading-changed', loading);
  }
  
  getGlobalLoading() {
    return this.getState('globalLoading') || false;
  }
  
  // 错误处理
  reportError(error, source) {
    this.emit('global-error', {
      error,
      source,
      timestamp: Date.now(),
    });
  }
  
  onGlobalError(callback) {
    this.on('global-error', callback);
  }
  
  // 清理方法
  cleanup() {
    // 清除所有事件监听器
    this.subscribers.forEach((callbacks, eventName) => {
      callbacks.forEach(callback => {
        this.eventBus.removeEventListener(eventName, callback);
      });
    });
    
    this.subscribers.clear();
    this.sharedStore.clear();
  }
}

// 全局通信实例
const microCommunication = new MicroFrontendCommunication();

// 挂载到全局对象
window.__MICRO_COMMUNICATION__ = microCommunication;

// React Hook封装
import { useEffect, useState, useCallback } from 'react';

export function useMicroCommunication() {
  return microCommunication;
}

export function useMicroState(key, initialValue) {
  const [value, setValue] = useState(() => 
    microCommunication.getState(key) ?? initialValue
  );
  
  useEffect(() => {
    const unsubscribe = microCommunication.onStateChange(key, (newValue) => {
      setValue(newValue);
    });
    
    return unsubscribe;
  }, [key]);
  
  const setMicroState = useCallback((newValue) => {
    microCommunication.setState(key, newValue);
  }, [key]);
  
  return [value, setMicroState];
}

export function useMicroEvent(eventName, callback) {
  useEffect(() => {
    microCommunication.on(eventName, callback);
    
    return () => {
      microCommunication.off(eventName, callback);
    };
  }, [eventName, callback]);
}

export function useMicroUser() {
  const [user, setUser] = useMicroState('currentUser', null);
  
  const updateUser = useCallback((userInfo) => {
    microCommunication.setUser(userInfo);
  }, []);
  
  const logout = useCallback(() => {
    microCommunication.setUser(null);
    microCommunication.navigateTo('/login');
  }, []);
  
  return { user, updateUser, logout };
}

// 使用示例
function UserApp() {
  const communication = useMicroCommunication();
  const [user, setUser] = useMicroUser();
  
  useEffect(() => {
    // 注册用户相关方法
    communication.registerMethod('getUserInfo', () => user);
    communication.registerMethod('refreshUserData', async () => {
      const userData = await fetchUserData();
      setUser(userData);
      return userData;
    });
    
    // 监听全局错误
    communication.onGlobalError((errorInfo) => {
      console.error('Global error:', errorInfo);
      // 显示错误提示
    });
    
    return () => {
      // 清理注册的方法
      communication.sharedStore.delete('method:getUserInfo');
      communication.sharedStore.delete('method:refreshUserData');
    };
  }, [user]);
  
  const handleUserAction = () => {
    // 触发用户相关事件
    communication.emit('user-action', {
      action: 'profile-updated',
      userId: user.id,
    });
  };
  
  return (
    <div>
      {/* 用户应用内容 */}
    </div>
  );
}

应用拆分策略

业务域拆分

// 业务域拆分策略
const BusinessDomainSplitting = {
  // 1. 垂直拆分 - 按业务功能
  verticalSplitting: {
    description: '按照业务功能将应用拆分为独立的微应用',
    examples: {
      ecommerce: {
        'user-management': '用户管理(注册、登录、个人信息)',
        'product-catalog': '商品目录(商品展示、搜索、分类)',
        'shopping-cart': '购物车(添加商品、结算)',
        'order-management': '订单管理(订单创建、支付、物流)',
        'customer-service': '客户服务(在线客服、售后)',
      },
      enterprise: {
        'hr-system': '人力资源(员工管理、考勤、薪资)',
        'finance-system': '财务系统(会计、报表、预算)',
        'project-management': '项目管理(任务、进度、资源)',
        'crm-system': '客户关系管理(客户信息、销售机会)',
      }
    },
    advantages: [
      '业务边界清晰',
      '团队职责明确',
      '技术栈可以差异化',
      '独立部署和扩展'
    ],
    challenges: [
      '跨域业务流程复杂',
      '数据一致性问题',
      '用户体验连贯性'
    ]
  },
  
  // 2. 水平拆分 - 按技术层次
  horizontalSplitting: {
    description: '按照技术架构层次拆分应用',
    layers: {
      'presentation-layer': '表现层(UI组件、页面)',
      'business-layer': '业务层(业务逻辑、工作流)',
      'data-layer': '数据层(数据访问、缓存)',
      'integration-layer': '集成层(API网关、消息队列)'
    },
    implementation: `
      // 表现层微应用
      const PresentationMicroApp = {
        components: ['Header', 'Navigation', 'Footer', 'Layout'],
        responsibilities: ['UI渲染', '用户交互', '状态管理'],
        technologies: ['React', 'Vue', 'Angular']
      };
      
      // 业务层微应用
      const BusinessMicroApp = {
        services: ['UserService', 'OrderService', 'PaymentService'],
        responsibilities: ['业务逻辑', '数据验证', '工作流程'],
        technologies: ['Node.js', 'Java', 'Python']
      };
    `
  },
  
  // 3. 混合拆分策略
  hybridSplitting: {
    description: '结合垂直和水平拆分的优势',
    strategy: `
      // 混合拆分示例
      const HybridArchitecture = {
        // 共享层(水平拆分)
        shared: {
          'ui-components': '通用UI组件库',
          'auth-service': '统一认证服务',
          'api-gateway': 'API网关',
          'monitoring': '监控和日志'
        },
        
        // 业务域(垂直拆分)
        domains: {
          user: {
            frontend: 'user-frontend',
            backend: 'user-service',
            database: 'user-db'
          },
          product: {
            frontend: 'product-frontend',
            backend: 'product-service',
            database: 'product-db'
          },
          order: {
            frontend: 'order-frontend',
            backend: 'order-service',
            database: 'order-db'
          }
        }
      };
    `
  }
};

// 拆分决策工具
class MicroFrontendSplittingDecision {
  constructor() {
    this.criteria = {
      teamSize: 0,
      businessComplexity: 0,
      technicalComplexity: 0,
      deploymentFrequency: 0,
      userTrafficVolume: 0,
    };
  }
  
  // 评估拆分必要性
  assessSplittingNeed(criteria) {
    this.criteria = { ...this.criteria, ...criteria };
    
    const scores = {
      teamSize: this.evaluateTeamSize(this.criteria.teamSize),
      businessComplexity: this.evaluateBusinessComplexity(this.criteria.businessComplexity),
      technicalComplexity: this.evaluateTechnicalComplexity(this.criteria.technicalComplexity),
      deploymentFrequency: this.evaluateDeploymentFrequency(this.criteria.deploymentFrequency),
      userTrafficVolume: this.evaluateUserTrafficVolume(this.criteria.userTrafficVolume),
    };
    
    const totalScore = Object.values(scores).reduce((sum, score) => sum + score, 0);
    const averageScore = totalScore / Object.keys(scores).length;
    
    return {
      scores,
      totalScore,
      averageScore,
      recommendation: this.getRecommendation(averageScore),
      details: this.getDetailedAnalysis(scores)
    };
  }
  
  evaluateTeamSize(size) {
    if (size <= 5) return 1; // 小团队,不建议拆分
    if (size <= 15) return 3; // 中等团队,可以考虑拆分
    return 5; // 大团队,建议拆分
  }
  
  evaluateBusinessComplexity(complexity) {
    // complexity: 1-5 (简单到复杂)
    return complexity;
  }
  
  evaluateTechnicalComplexity(complexity) {
    // complexity: 1-5 (简单到复杂)
    return complexity;
  }
  
  evaluateDeploymentFrequency(frequency) {
    // frequency: 每月部署次数
    if (frequency <= 2) return 1;
    if (frequency <= 8) return 3;
    return 5;
  }
  
  evaluateUserTrafficVolume(volume) {
    // volume: 1-5 (低到高)
    return volume;
  }
  
  getRecommendation(averageScore) {
    if (averageScore <= 2) {
      return {
        level: 'low',
        suggestion: '不建议拆分',
        reason: '当前规模和复杂度不需要微前端架构'
      };
    } else if (averageScore <= 3.5) {
      return {
        level: 'medium',
        suggestion: '可以考虑拆分',
        reason: '具备一定的拆分条件,可以逐步实施'
      };
    } else {
      return {
        level: 'high',
        suggestion: '强烈建议拆分',
        reason: '复杂度和规模已经达到需要微前端架构的程度'
      };
    }
  }
  
  getDetailedAnalysis(scores) {
    const analysis = [];
    
    if (scores.teamSize >= 4) {
      analysis.push('团队规模较大,适合并行开发');
    }
    
    if (scores.businessComplexity >= 4) {
      analysis.push('业务复杂度高,建议按业务域拆分');
    }
    
    if (scores.technicalComplexity >= 4) {
      analysis.push('技术复杂度高,可以采用不同技术栈');
    }
    
    if (scores.deploymentFrequency >= 4) {
      analysis.push('部署频繁,独立部署能提高效率');
    }
    
    if (scores.userTrafficVolume >= 4) {
      analysis.push('用户量大,需要独立扩展能力');
    }
    
    return analysis;
  }
  
  // 生成拆分方案
  generateSplittingPlan(businessDomains, technicalRequirements) {
    const plan = {
      strategy: 'hybrid', // vertical, horizontal, hybrid
      microApps: [],
      sharedServices: [],
      infrastructure: [],
      migrationSteps: []
    };
    
    // 根据业务域生成微应用
    businessDomains.forEach(domain => {
      plan.microApps.push({
        name: domain.name,
        description: domain.description,
        team: domain.team,
        technologies: domain.preferredTech,
        dependencies: domain.dependencies,
        apis: domain.apis
      });
    });
    
    // 识别共享服务
    plan.sharedServices = [
      'authentication',
      'authorization',
      'logging',
      'monitoring',
      'configuration',
      'ui-components'
    ];
    
    // 基础设施需求
    plan.infrastructure = [
      'api-gateway',
      'service-discovery',
      'load-balancer',
      'cdn',
      'monitoring-system',
      'ci-cd-pipeline'
    ];
    
    // 迁移步骤
    plan.migrationSteps = [
      '1. 建立基础设施和共享服务',
      '2. 识别和拆分第一个微应用',
      '3. 建立通信机制和集成测试',
      '4. 逐步迁移其他业务模块',
      '5. 优化性能和用户体验',
      '6. 建立监控和运维体系'
    ];
    
    return plan;
  }
}

// 使用示例
const splittingDecision = new MicroFrontendSplittingDecision();

const assessment = splittingDecision.assessSplittingNeed({
  teamSize: 20,
  businessComplexity: 4,
  technicalComplexity: 3,
  deploymentFrequency: 12,
  userTrafficVolume: 4
});

console.log('拆分评估结果:', assessment);

const businessDomains = [
  {
    name: 'user-management',
    description: '用户管理系统',
    team: 'user-team',
    preferredTech: ['React', 'Node.js'],
    dependencies: ['auth-service'],
    apis: ['/api/users', '/api/profiles']
  },
  {
    name: 'product-catalog',
    description: '商品目录系统',
    team: 'product-team',
    preferredTech: ['Vue', 'Java'],
    dependencies: ['search-service'],
    apis: ['/api/products', '/api/categories']
  }
];

const splittingPlan = splittingDecision.generateSplittingPlan(
  businessDomains,
  { performance: 'high', scalability: 'high' }
);

console.log('拆分方案:', splittingPlan);

总结

微前端架构的核心要点:

  1. 架构设计:技术栈无关、独立部署、团队自治
  2. 技术方案:Module Federation、iframe、Web Components等
  3. 应用拆分:垂直拆分、水平拆分、混合策略
  4. 通信机制:事件总线、共享状态、方法调用
  5. 工程实践:生命周期管理、错误边界、性能优化

微前端架构能够有效解决大型前端应用的复杂性问题,提高开发效率和系统可维护性,是现代前端架构的重要发展方向。