微前端之样式隔离、JS隔离、公共依赖、路由状态更新、通信方式对比

微前端之样式隔离、JS隔离、公共依赖、路由状态更新、通信方式对比

1. 样式隔离解决方案对比

样式隔离是微前端架构中的核心问题,不同框架采用了不同的技术方案来解决样式冲突。

1.1 主流隔离方案

Shadow DOM隔离

Shadow DOM提供了原生的样式隔离能力,创建完全封闭的样式作用域。

javascript 复制代码
// Shadow DOM样式隔离实现
class ShadowDOMStyleIsolation {
  constructor(container, appName) {
    this.container = container;
    this.appName = appName;
    this.shadowRoot = null;
    this.init();
  }

  init() {
    // 创建Shadow DOM
    this.shadowRoot = this.container.attachShadow({ mode: 'open' });
    
    // 创建应用容器
    const appContainer = document.createElement('div');
    appContainer.id = `${this.appName}-root`;
    this.shadowRoot.appendChild(appContainer);
  }

  // 注入样式到Shadow DOM
  injectStyles(cssText) {
    const style = document.createElement('style');
    style.textContent = cssText;
    this.shadowRoot.appendChild(style);
  }

  // 处理外部样式文件
  async loadExternalStyles(styleUrls) {
    const loadPromises = styleUrls.map(async (url) => {
      const response = await fetch(url);
      const cssText = await response.text();
      this.injectStyles(cssText);
    });
    
    await Promise.all(loadPromises);
  }

  // 获取应用容器
  getAppContainer() {
    return this.shadowRoot.querySelector(`#${this.appName}-root`);
  }
}

// 使用示例
const styleIsolation = new ShadowDOMStyleIsolation(
  document.getElementById('app-container'),
  'micro-app'
);

// 加载应用样式
await styleIsolation.loadExternalStyles([
  'http://localhost:3001/static/css/main.css',
  'http://localhost:3001/static/css/components.css'
]);
CSS Scoped隔离

通过添加唯一前缀或后缀来实现样式作用域隔离。

javascript 复制代码
// CSS Scoped样式隔离
class ScopedStyleIsolation {
  constructor(appName, scopeId) {
    this.appName = appName;
    this.scopeId = scopeId || `micro-app-${appName}-${Date.now()}`;
    this.processedStyles = new Set();
  }

  // 处理CSS规则,添加作用域
  processCSSRules(cssText) {
    // 处理选择器,添加作用域前缀
    const processedCSS = cssText.replace(
      /([^{}]+)\{/g,
      (match, selector) => {
        // 过滤掉一些全局选择器
        if (this.isGlobalSelector(selector.trim())) {
          return match;
        }
        
        // 添加作用域前缀
        const scopedSelector = selector
          .split(',')
          .map(s => `[data-micro-app="${this.scopeId}"] ${s.trim()}`)
          .join(', ');
        
        return `${scopedSelector} {`;
      }
    );

    return processedCSS;
  }

  // 判断是否为全局选择器
  isGlobalSelector(selector) {
    const globalSelectors = [
      'html', 'body', '*', 
      /^@/, // @media, @keyframes等
      /^:root/,
      /^:before/, /^:after/
    ];
    
    return globalSelectors.some(pattern => {
      if (typeof pattern === 'string') {
        return selector === pattern;
      }
      return pattern.test(selector);
    });
  }

  // 动态插入作用域样式
  injectScopedStyles(cssText, containerId) {
    if (this.processedStyles.has(cssText)) {
      return;
    }

    const processedCSS = this.processCSSRules(cssText);
    const styleElement = document.createElement('style');
    styleElement.setAttribute('data-app', this.appName);
    styleElement.textContent = processedCSS;
    
    document.head.appendChild(styleElement);
    this.processedStyles.add(cssText);

    // 为容器添加作用域标识
    const container = document.getElementById(containerId);
    if (container) {
      container.setAttribute('data-micro-app', this.scopeId);
    }
  }

  // 清理应用样式
  cleanup() {
    const appStyles = document.querySelectorAll(`style[data-app="${this.appName}"]`);
    appStyles.forEach(style => style.remove());
    this.processedStyles.clear();
  }
}

// 使用示例
const scopedIsolation = new ScopedStyleIsolation('react-app');

// 处理和注入样式
const cssContent = `
  .header { background: blue; }
  .content { padding: 20px; }
  body { margin: 0; }
`;

scopedIsolation.injectScopedStyles(cssContent, 'react-app-container');
CSS Modules隔离

通过构建时的CSS Modules技术实现样式模块化。

javascript 复制代码
// CSS Modules构建配置
const webpackConfig = {
  module: {
    rules: [
      {
        test: /\.module\.css$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              modules: {
                localIdentName: '[name]__[local]__[hash:base64:5]',
                // 自定义类名生成函数
                getLocalIdent: (context, localIdentName, localName) => {
                  const appName = context.resourcePath.includes('micro-app') 
                    ? 'micro-app' 
                    : 'main-app';
                  return `${appName}__${localName}__${generateHash()}`;
                }
              }
            }
          }
        ]
      }
    ]
  }
};

// 运行时CSS Modules处理
class CSSModulesIsolation {
  constructor(appName) {
    this.appName = appName;
    this.moduleMap = new Map();
    this.classNameGenerator = new ClassNameGenerator(appName);
  }

  // 处理CSS Modules
  processCSSModules(cssText, modulePath) {
    const classMap = {};
    
    // 提取类名并生成映射
    const processedCSS = cssText.replace(
      /\.([a-zA-Z][\w-]*)/g,
      (match, className) => {
        const scopedName = this.classNameGenerator.generate(className, modulePath);
        classMap[className] = scopedName;
        return `.${scopedName}`;
      }
    );

    this.moduleMap.set(modulePath, classMap);
    return { processedCSS, classMap };
  }

  // 获取作用域类名
  getClassName(modulePath, className) {
    const classMap = this.moduleMap.get(modulePath);
    return classMap ? classMap[className] : className;
  }
}

// 类名生成器
class ClassNameGenerator {
  constructor(appName) {
    this.appName = appName;
    this.counter = 0;
  }

  generate(className, filePath) {
    const fileHash = this.generateFileHash(filePath);
    const uniqueId = this.counter++;
    return `${this.appName}__${className}__${fileHash}__${uniqueId}`;
  }

  generateFileHash(filePath) {
    // 简单哈希算法
    let hash = 0;
    for (let i = 0; i < filePath.length; i++) {
      const char = filePath.charCodeAt(i);
      hash = ((hash << 5) - hash) + char;
      hash = hash & hash; // 转换为32位整数
    }
    return Math.abs(hash).toString(36).substr(0, 5);
  }
}

1.2 各框架样式隔离对比

javascript 复制代码
// 不同微前端框架的样式隔离对比
const styleIsolationComparison = {
  'single-spa': {
    method: 'Manual Scoping',
    implementation: `
      // 手动作用域处理
      const styles = getCSSText();
      const scopedStyles = addScopeToCSS(styles, appName);
      injectStyles(scopedStyles);
    `,
    pros: ['灵活度高', '性能较好'],
    cons: ['需要手动处理', '容易遗漏']
  },

  'qiankun': {
    method: 'Dynamic Stylesheet',
    implementation: `
      // 动态样式表管理
      sandbox.patchStrictSandbox = () => {
        // 劫持样式插入
        const originalAppendChild = HTMLHeadElement.prototype.appendChild;
        HTMLHeadElement.prototype.appendChild = function(element) {
          if (element.tagName === 'STYLE') {
            element.setAttribute('data-qiankun', appName);
          }
          return originalAppendChild.call(this, element);
        };
      };
    `,
    pros: ['自动处理', '兼容性好'],
    cons: ['运行时开销', '可能影响性能']
  },

  'micro-app': {
    method: 'ScopedCSS + Shadow DOM',
    implementation: `
      // 样式作用域 + Shadow DOM
      class MicroAppStyleIsolation {
        processCSSText(cssText) {
          return cssText.replace(/\\b([^{}]+){/g, (all, selector) => {
            return \`micro-app[name="\${this.appName}"] \${selector}{\`;
          });
        }
      }
    `,
    pros: ['隔离彻底', '性能较好'],
    cons: ['兼容性限制', '调试困难']
  },

  'wujie': {
    method: 'Iframe + CSS Proxy',
    implementation: `
      // iframe天然隔离 + CSS代理
      const iframeDocument = iframe.contentDocument;
      const style = iframeDocument.createElement('style');
      style.textContent = cssText;
      iframeDocument.head.appendChild(style);
    `,
    pros: ['天然隔离', '兼容性好'],
    cons: ['通信复杂', '性能开销大']
  },

  'garfish': {
    method: 'Scoped CSS + VM Sandbox',
    implementation: `
      // 作用域CSS + 虚拟机沙箱
      const sandbox = new VMSandbox();
      sandbox.execScript(\`
        const originalCreateElement = document.createElement;
        document.createElement = function(tagName) {
          const element = originalCreateElement.call(this, tagName);
          if (tagName === 'style') {
            element.scoped = true;
          }
          return element;
        };
      \`);
    `,
    pros: ['隔离完善', '性能均衡'],
    cons: ['复杂度高', '学习成本大']
  }
};

1.3 样式隔离方案选择流程图

graph TD A[开始选择样式隔离方案] --> B{是否需要完全隔离?} B -->|是| C{浏览器支持Shadow DOM?} B -->|否| D[CSS Scoped方案] C -->|是| E[Shadow DOM隔离] C -->|否| F{构建时处理?} F -->|是| G[CSS Modules] F -->|否| H[动态作用域] D --> I[添加唯一前缀] E --> J[创建Shadow Root] G --> K[构建时类名转换] H --> L[运行时样式处理] I --> M[样式隔离完成] J --> M K --> M L --> M style E fill:#e8f5e8 style G fill:#e3f2fd style H fill:#fff3e0 style D fill:#fce4ec

2. JS隔离解决方案对比

JavaScript隔离确保不同微应用之间的全局变量、原型链、事件监听器等不会相互干扰。

2.1 沙箱隔离技术

Proxy沙箱

基于ES6 Proxy实现的JavaScript沙箱隔离。

javascript 复制代码
// Proxy沙箱实现
class ProxySandbox {
  constructor(appName) {
    this.appName = appName;
    this.isRunning = false;
    this.modifiedPropsMap = new Map();
    this.addedPropsMap = new Map();
    this.currentUpdatedPropsValueMap = new Map();
    
    // 创建代理对象
    this.proxyWindow = this.createProxyWindow();
  }

  createProxyWindow() {
    const rawWindow = window;
    const fakeWindow = Object.create(null);

    return new Proxy(fakeWindow, {
      set: (target, property, value, receiver) => {
        if (this.isRunning) {
          // 记录属性变更
          if (!rawWindow.hasOwnProperty(property)) {
            this.addedPropsMap.set(property, value);
          } else if (!this.modifiedPropsMap.has(property)) {
            this.modifiedPropsMap.set(property, rawWindow[property]);
          }

          this.currentUpdatedPropsValueMap.set(property, value);
          
          // 设置到目标对象
          target[property] = value;
          return true;
        }

        console.warn(`[${this.appName}] 沙箱未激活,无法设置属性 ${property}`);
        return true;
      },

      get: (target, property, receiver) => {
        // 优先从代理对象获取
        if (target.hasOwnProperty(property)) {
          return target[property];
        }

        // 从原始window获取
        const rawValue = rawWindow[property];
        
        // 绑定函数上下文
        if (typeof rawValue === 'function' && !this.isConstructor(rawValue)) {
          return rawValue.bind(rawWindow);
        }

        return rawValue;
      },

      has: (target, property) => {
        return property in target || property in rawWindow;
      },

      ownKeys: (target) => {
        return [...Reflect.ownKeys(rawWindow), ...Reflect.ownKeys(target)];
      }
    });
  }

  // 判断是否为构造函数
  isConstructor(fn) {
    const functionStr = fn.toString();
    return /^class\s/.test(functionStr) || /^function\s+[A-Z]/.test(functionStr);
  }

  // 激活沙箱
  active() {
    if (!this.isRunning) {
      this.isRunning = true;
      
      // 恢复之前的状态
      this.currentUpdatedPropsValueMap.forEach((value, property) => {
        this.proxyWindow[property] = value;
      });

      console.log(`[${this.appName}] 沙箱已激活`);
    }
  }

  // 失活沙箱
  inactive() {
    if (this.isRunning) {
      this.isRunning = false;

      // 清理添加的属性
      this.addedPropsMap.forEach((_, property) => {
        delete window[property];
      });

      // 恢复修改的属性
      this.modifiedPropsMap.forEach((originalValue, property) => {
        window[property] = originalValue;
      });

      console.log(`[${this.appName}] 沙箱已失活`);
    }
  }

  // 执行代码
  execScript(script) {
    if (!this.isRunning) {
      console.warn(`[${this.appName}] 沙箱未激活,无法执行脚本`);
      return;
    }

    try {
      // 创建执行上下文
      const execFunction = new Function('window', 'self', 'globalThis', script);
      return execFunction(this.proxyWindow, this.proxyWindow, this.proxyWindow);
    } catch (error) {
      console.error(`[${this.appName}] 脚本执行失败:`, error);
      throw error;
    }
  }
}

// 使用示例
const sandbox = new ProxySandbox('micro-app');
sandbox.active();

// 执行子应用代码
sandbox.execScript(`
  window.myAppData = { name: 'micro-app' };
  console.log('子应用初始化完成');
  
  // 不会污染全局window
  window.setTimeout = function() {
    console.log('自定义setTimeout');
  };
`);

sandbox.inactive();
快照沙箱

通过记录和恢复全局状态快照实现隔离。

javascript 复制代码
// 快照沙箱实现
class SnapshotSandbox {
  constructor(appName) {
    this.appName = appName;
    this.isRunning = false;
    this.windowSnapshot = {};
    this.modifyPropsMap = {};
  }

  // 激活沙箱
  active() {
    if (this.isRunning) return;

    // 记录当前window状态快照
    this.windowSnapshot = {};
    for (const prop in window) {
      this.windowSnapshot[prop] = window[prop];
    }

    // 恢复之前的修改
    Object.keys(this.modifyPropsMap).forEach(property => {
      window[property] = this.modifyPropsMap[property];
    });

    this.isRunning = true;
    console.log(`[${this.appName}] 快照沙箱已激活`);
  }

  // 失活沙箱
  inactive() {
    if (!this.isRunning) return;

    // 记录修改的属性
    this.modifyPropsMap = {};
    for (const prop in window) {
      if (window[prop] !== this.windowSnapshot[prop]) {
        this.modifyPropsMap[prop] = window[prop];
        // 恢复原始值
        window[prop] = this.windowSnapshot[prop];
      }
    }

    // 清理新增的属性
    for (const prop in window) {
      if (!(prop in this.windowSnapshot)) {
        delete window[prop];
      }
    }

    this.isRunning = false;
    console.log(`[${this.appName}] 快照沙箱已失活`);
  }

  // 执行脚本
  execScript(script) {
    if (!this.isRunning) {
      console.warn(`[${this.appName}] 沙箱未激活`);
      return;
    }

    try {
      // 直接在全局作用域执行
      (0, eval)(script);
    } catch (error) {
      console.error(`[${this.appName}] 脚本执行失败:`, error);
      throw error;
    }
  }
}

// 使用示例
const snapshotSandbox = new SnapshotSandbox('legacy-app');
snapshotSandbox.active();

snapshotSandbox.execScript(`
  window.legacyData = { version: '1.0' };
  var globalVar = 'legacy app variable';
`);

snapshotSandbox.inactive();
iframe沙箱

利用iframe的天然隔离特性实现完全的JavaScript隔离。

javascript 复制代码
// iframe沙箱实现
class IframeSandbox {
  constructor(appName, container) {
    this.appName = appName;
    this.container = container;
    this.iframe = null;
    this.iframeWindow = null;
    this.communicationBridge = null;
    this.init();
  }

  init() {
    // 创建iframe
    this.iframe = document.createElement('iframe');
    this.iframe.style.cssText = `
      width: 100%;
      height: 100%;
      border: none;
    `;
    
    // 设置iframe src为空白页面
    this.iframe.src = 'about:blank';
    
    this.container.appendChild(this.iframe);
    this.iframeWindow = this.iframe.contentWindow;

    // 建立通信桥梁
    this.setupCommunicationBridge();
    
    // 初始化iframe环境
    this.setupIframeEnvironment();
  }

  // 设置iframe环境
  setupIframeEnvironment() {
    const iframeDoc = this.iframe.contentDocument;
    
    // 写入基础HTML结构
    iframeDoc.open();
    iframeDoc.write(`
      <!DOCTYPE html>
      <html>
        <head>
          <meta charset="utf-8">
          <title>${this.appName}</title>
        </head>
        <body>
          <div id="app"></div>
        </body>
      </html>
    `);
    iframeDoc.close();

    // 同步主应用的基础能力
    this.syncMainAppCapabilities();
  }

  // 同步主应用能力
  syncMainAppCapabilities() {
    const iframeWindow = this.iframeWindow;
    
    // 同步fetch
    iframeWindow.fetch = window.fetch.bind(window);
    
    // 同步XMLHttpRequest
    iframeWindow.XMLHttpRequest = window.XMLHttpRequest;
    
    // 同步localStorage(可选)
    Object.defineProperty(iframeWindow, 'localStorage', {
      get: () => window.localStorage,
      configurable: true
    });

    // 同步sessionStorage(可选)
    Object.defineProperty(iframeWindow, 'sessionStorage', {
      get: () => window.sessionStorage,
      configurable: true
    });

    // 代理console
    iframeWindow.console = new Proxy(window.console, {
      get: (target, property) => {
        const method = target[property];
        if (typeof method === 'function') {
          return method.bind(target);
        }
        return method;
      }
    });
  }

  // 建立通信桥梁
  setupCommunicationBridge() {
    this.communicationBridge = {
      // 向iframe发送消息
      postMessage: (data) => {
        this.iframeWindow.postMessage({
          type: 'main-to-iframe',
          data,
          appName: this.appName
        }, '*');
      },

      // 监听iframe消息
      onMessage: (callback) => {
        window.addEventListener('message', (event) => {
          if (event.source === this.iframeWindow && 
              event.data.type === 'iframe-to-main' &&
              event.data.appName === this.appName) {
            callback(event.data.data);
          }
        });
      }
    };

    // 在iframe中设置通信代理
    this.iframeWindow.addEventListener('load', () => {
      this.execScript(`
        window.parent.postMessage = function(data) {
          parent.postMessage({
            type: 'iframe-to-main',
            data: data,
            appName: '${this.appName}'
          }, '*');
        };

        window.addEventListener('message', function(event) {
          if (event.data.type === 'main-to-iframe' && 
              event.data.appName === '${this.appName}') {
            // 触发iframe内的消息处理
            window.dispatchEvent(new CustomEvent('mainMessage', {
              detail: event.data.data
            }));
          }
        });
      `);
    });
  }

  // 在iframe中执行脚本
  execScript(script) {
    try {
      const scriptElement = this.iframe.contentDocument.createElement('script');
      scriptElement.textContent = script;
      this.iframe.contentDocument.head.appendChild(scriptElement);
    } catch (error) {
      console.error(`[${this.appName}] iframe脚本执行失败:`, error);
      throw error;
    }
  }

  // 加载外部脚本
  async loadScript(src) {
    return new Promise((resolve, reject) => {
      const script = this.iframe.contentDocument.createElement('script');
      script.src = src;
      script.onload = resolve;
      script.onerror = reject;
      this.iframe.contentDocument.head.appendChild(script);
    });
  }

  // 销毁沙箱
  destroy() {
    if (this.iframe && this.iframe.parentNode) {
      this.iframe.parentNode.removeChild(this.iframe);
    }
    this.iframe = null;
    this.iframeWindow = null;
    this.communicationBridge = null;
  }
}

// 使用示例
const iframeSandbox = new IframeSandbox('isolated-app', document.getElementById('app-container'));

// 加载应用脚本
await iframeSandbox.loadScript('http://localhost:3001/static/js/app.js');

// 执行初始化代码
iframeSandbox.execScript(`
  // 在完全隔离的iframe环境中执行
  window.myAppConfig = { isolated: true };
  console.log('iframe应用初始化完成');
`);

// 建立通信
iframeSandbox.communicationBridge.onMessage((data) => {
  console.log('收到iframe消息:', data);
});

iframeSandbox.communicationBridge.postMessage({
  type: 'init',
  config: { theme: 'dark' }
});

2.2 各框架JS隔离对比

javascript 复制代码
// JS隔离方案对比表
const jsIsolationComparison = {
  frameworks: {
    'single-spa': {
      isolation: 'None',
      description: '无隔离,依赖应用自身管理',
      implementation: '手动命名空间管理',
      performance: '★★★★★',
      compatibility: '★★★★★',
      security: '★★☆☆☆'
    },

    'qiankun': {
      isolation: 'Proxy Sandbox',
      description: '基于Proxy的多实例沙箱',
      implementation: `
        // Proxy沙箱核心实现
        const sandbox = new ProxySandbox(appName);
        sandbox.active();
        execScript(code, sandbox.proxy);
        sandbox.inactive();
      `,
      performance: '★★★★☆',
      compatibility: '★★★★☆',
      security: '★★★★☆'
    },

    'micro-app': {
      isolation: 'with + Proxy',
      description: 'with语句 + Proxy劫持',
      implementation: `
        // with + Proxy实现
        const sandbox = new Proxy(window, {
          get: (target, key) => {
            return key in appScope ? appScope[key] : target[key];
          },
          set: (target, key, value) => {
            appScope[key] = value;
            return true;
          }
        });
        with(sandbox) { eval(code); }
      `,
      performance: '★★★☆☆',
      compatibility: '★★★☆☆',
      security: '★★★☆☆'
    },

    'wujie': {
      isolation: 'Iframe Sandbox',
      description: 'iframe天然隔离',
      implementation: `
        // iframe沙箱
        const iframe = document.createElement('iframe');
        iframe.src = 'about:blank';
        const iframeWindow = iframe.contentWindow;
        iframeWindow.eval(code);
      `,
      performance: '★★★☆☆',
      compatibility: '★★★★★',
      security: '★★★★★'
    },

    'garfish': {
      isolation: 'VM Sandbox',
      description: '虚拟机沙箱隔离',
      implementation: `
        // VM沙箱实现
        const vm = new VMSandbox({
          globalContext: createFakeWindow(),
          strictMode: true
        });
        vm.execScript(code);
      `,
      performance: '★★★★☆',
      compatibility: '★★★★☆',
      security: '★★★★☆'
    }
  }
};

// 性能对比测试
class JSIsolationPerformanceTest {
  constructor() {
    this.testResults = {};
  }

  // 测试沙箱创建性能
  async testSandboxCreation(SandboxClass, iterations = 1000) {
    const startTime = performance.now();
    
    for (let i = 0; i < iterations; i++) {
      const sandbox = new SandboxClass(`test-app-${i}`);
      sandbox.active && sandbox.active();
      sandbox.inactive && sandbox.inactive();
    }
    
    const endTime = performance.now();
    return endTime - startTime;
  }

  // 测试脚本执行性能
  async testScriptExecution(sandbox, script, iterations = 100) {
    const startTime = performance.now();
    
    for (let i = 0; i < iterations; i++) {
      sandbox.execScript(script);
    }
    
    const endTime = performance.now();
    return endTime - startTime;
  }

  // 运行完整性能测试
  async runFullTest() {
    const testScript = `
      window.testVar = Math.random();
      for (let i = 0; i < 1000; i++) {
        window['prop' + i] = i;
      }
    `;

    // 测试Proxy沙箱
    const proxyTime = await this.testSandboxCreation(ProxySandbox);
    console.log('Proxy沙箱创建时间:', proxyTime + 'ms');

    // 测试快照沙箱
    const snapshotTime = await this.testSandboxCreation(SnapshotSandbox);
    console.log('快照沙箱创建时间:', snapshotTime + 'ms');

    return {
      proxy: proxyTime,
      snapshot: snapshotTime
    };
  }
}

2.3 JS隔离技术选择流程图

graph TD A[开始选择JS隔离方案] --> B{性能要求} B -->|高性能| C{兼容性要求} B -->|一般| D{安全要求} C -->|现代浏览器| E[Proxy沙箱] C -->|兼容IE| F[快照沙箱] D -->|高安全| G[iframe沙箱] D -->|一般| H{代码复杂度} H -->|简单| I[with + Proxy] H -->|复杂| J[VM沙箱] E --> K[实现Proxy代理] F --> L[记录全局状态快照] G --> M[创建iframe隔离] I --> N[with语句劫持] J --> O[虚拟机执行] K --> P[JS隔离完成] L --> P M --> P N --> P O --> P style E fill:#e8f5e8 style G fill:#e3f2fd style J fill:#fff3e0 style F fill:#fce4ec

3. 公共依赖管理方案对比

公共依赖管理是微前端架构中提升性能和减少重复加载的关键技术。

3.1 依赖共享策略

模块联邦(Module Federation)

Webpack 5的模块联邦提供了运行时的依赖共享能力。

javascript 复制代码
// 主应用的webpack配置
const ModuleFederationPlugin = require('@module-federation/webpack');

module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      name: 'main_app',
      remotes: {
        micro_app_1: 'micro_app_1@http://localhost:3001/remoteEntry.js',
        micro_app_2: 'micro_app_2@http://localhost:3002/remoteEntry.js'
      },
      shared: {
        react: { 
          singleton: true,
          requiredVersion: '^18.2.0',
          eager: true 
        },
        'react-dom': { 
          singleton: true,
          requiredVersion: '^18.2.0',
          eager: true 
        },
        'react-router-dom': {
          singleton: true,
          version: '^6.0.0'
        },
        lodash: {
          singleton: false,
          version: '^4.17.21'
        }
      }
    })
  ]
};

// 微应用的webpack配置
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      name: 'micro_app_1',
      filename: 'remoteEntry.js',
      exposes: {
        './App': './src/App',
        './utils': './src/utils'
      },
      shared: {
        react: { 
          singleton: true,
          requiredVersion: '^18.2.0'
        },
        'react-dom': { 
          singleton: true,
          requiredVersion: '^18.2.0'
        }
      }
    })
  ]
};

// 运行时动态加载管理
class ModuleFederationManager {
  constructor() {
    this.loadedRemotes = new Map();
    this.sharedModules = new Map();
    this.loadingPromises = new Map();
  }

  // 动态加载远程模块
  async loadRemoteModule(remoteName, moduleName) {
    const remoteKey = `${remoteName}/${moduleName}`;
    
    if (this.loadedRemotes.has(remoteKey)) {
      return this.loadedRemotes.get(remoteKey);
    }

    if (this.loadingPromises.has(remoteKey)) {
      return this.loadingPromises.get(remoteKey);
    }

    const loadingPromise = this.performRemoteLoad(remoteName, moduleName);
    this.loadingPromises.set(remoteKey, loadingPromise);

    try {
      const module = await loadingPromise;
      this.loadedRemotes.set(remoteKey, module);
      return module;
    } finally {
      this.loadingPromises.delete(remoteKey);
    }
  }

  async performRemoteLoad(remoteName, moduleName) {
    try {
      // 动态导入远程模块
      const container = window[remoteName];
      
      if (!container) {
        throw new Error(`Remote container ${remoteName} not found`);
      }

      // 初始化容器
      await container.init(__webpack_share_scopes__.default);
      
      // 获取模块工厂
      const factory = await container.get(moduleName);
      
      // 执行模块
      const module = factory();
      
      return module;
    } catch (error) {
      console.error(`Failed to load remote module ${remoteName}/${moduleName}:`, error);
      throw error;
    }
  }

  // 注册共享模块
  registerSharedModule(name, module, version) {
    this.sharedModules.set(name, {
      module,
      version,
      timestamp: Date.now()
    });
  }

  // 获取共享模块
  getSharedModule(name, requiredVersion) {
    const shared = this.sharedModules.get(name);
    
    if (!shared) {
      return null;
    }

    // 版本兼容性检查
    if (requiredVersion && !this.isVersionCompatible(shared.version, requiredVersion)) {
      console.warn(`Version mismatch for ${name}: required ${requiredVersion}, got ${shared.version}`);
      return null;
    }

    return shared.module;
  }

  // 版本兼容性检查
  isVersionCompatible(currentVersion, requiredVersion) {
    // 简单的语义版本检查
    const parseVersion = (version) => {
      const cleaned = version.replace(/[^\d.]/g, '');
      return cleaned.split('.').map(num => parseInt(num, 10));
    };

    const current = parseVersion(currentVersion);
    const required = parseVersion(requiredVersion);

    // 主版本号必须匹配
    return current[0] === required[0];
  }
}

// 使用示例
const federationManager = new ModuleFederationManager();

// 加载远程组件
async function loadMicroApp() {
  try {
    const MicroApp = await federationManager.loadRemoteModule('micro_app_1', './App');
    
    // 渲染组件
    const element = React.createElement(MicroApp.default);
    ReactDOM.render(element, document.getElementById('micro-app-container'));
    
  } catch (error) {
    console.error('Failed to load micro app:', error);
  }
}
SystemJS依赖管理

基于SystemJS的运行时依赖管理和模块加载。

javascript 复制代码
// SystemJS依赖管理器
class SystemJSDependencyManager {
  constructor() {
    this.sharedDependencies = new Map();
    this.moduleCache = new Map();
    this.importMap = new Map();
    this.init();
  }

  init() {
    // 配置SystemJS
    System.config({
      map: {
        'react': '/shared/react@18.2.0/index.js',
        'react-dom': '/shared/react-dom@18.2.0/index.js',
        'lodash': '/shared/lodash@4.17.21/lodash.min.js',
        'axios': '/shared/axios@1.3.0/dist/axios.min.js'
      }
    });

    // 预加载共享依赖
    this.preloadSharedDependencies();
  }

  // 预加载共享依赖
  async preloadSharedDependencies() {
    const sharedDeps = [
      { name: 'react', version: '18.2.0' },
      { name: 'react-dom', version: '18.2.0' },
      { name: 'lodash', version: '4.17.21' }
    ];

    const loadPromises = sharedDeps.map(dep => this.loadSharedDependency(dep));
    
    try {
      await Promise.all(loadPromises);
      console.log('共享依赖预加载完成');
    } catch (error) {
      console.error('共享依赖预加载失败:', error);
    }
  }

  // 加载共享依赖
  async loadSharedDependency({ name, version }) {
    const cacheKey = `${name}@${version}`;
    
    if (this.sharedDependencies.has(cacheKey)) {
      return this.sharedDependencies.get(cacheKey);
    }

    try {
      const module = await System.import(name);
      
      this.sharedDependencies.set(cacheKey, {
        module,
        version,
        loadTime: Date.now()
      });

      console.log(`共享依赖加载成功: ${cacheKey}`);
      return module;
      
    } catch (error) {
      console.error(`共享依赖加载失败: ${cacheKey}`, error);
      throw error;
    }
  }

  // 动态导入模块
  async importModule(modulePath, dependencies = []) {
    // 确保依赖已加载
    await this.ensureDependencies(dependencies);
    
    try {
      const module = await System.import(modulePath);
      
      // 缓存模块
      this.moduleCache.set(modulePath, module);
      
      return module;
    } catch (error) {
      console.error(`模块导入失败: ${modulePath}`, error);
      throw error;
    }
  }

  // 确保依赖已加载
  async ensureDependencies(dependencies) {
    const loadPromises = dependencies.map(dep => {
      if (typeof dep === 'string') {
        return this.loadSharedDependency({ name: dep, version: 'latest' });
      }
      return this.loadSharedDependency(dep);
    });

    await Promise.all(loadPromises);
  }

  // 获取依赖统计信息
  getDependencyStats() {
    const stats = {
      totalShared: this.sharedDependencies.size,
      totalCached: this.moduleCache.size,
      sharedDetails: [],
      memoryUsage: 0
    };

    this.sharedDependencies.forEach((dep, key) => {
      stats.sharedDetails.push({
        name: key,
        version: dep.version,
        loadTime: dep.loadTime,
        size: this.estimateModuleSize(dep.module)
      });
    });

    return stats;
  }

  // 估算模块大小
  estimateModuleSize(module) {
    try {
      return JSON.stringify(module).length;
    } catch {
      return 0;
    }
  }

  // 清理无用模块
  cleanup() {
    const now = Date.now();
    const maxAge = 30 * 60 * 1000; // 30分钟

    this.sharedDependencies.forEach((dep, key) => {
      if (now - dep.loadTime > maxAge) {
        this.sharedDependencies.delete(key);
        console.log(`清理过期依赖: ${key}`);
      }
    });
  }
}

// 使用示例
const dependencyManager = new SystemJSDependencyManager();

// 加载微应用
async function loadMicroAppWithDependencies() {
  try {
    // 确保React相关依赖已加载
    await dependencyManager.ensureDependencies([
      { name: 'react', version: '18.2.0' },
      { name: 'react-dom', version: '18.2.0' }
    ]);

    // 导入微应用模块
    const MicroApp = await dependencyManager.importModule(
      'http://localhost:3001/micro-app.js',
      ['react', 'react-dom']
    );

    // 渲染微应用
    MicroApp.render('#micro-app-container');
    
  } catch (error) {
    console.error('微应用加载失败:', error);
  }
}

// 定期清理
setInterval(() => {
  dependencyManager.cleanup();
}, 10 * 60 * 1000); // 每10分钟清理一次
外部化依赖(Externals)

通过Webpack externals配置实现依赖外部化。

javascript 复制代码
// 外部化依赖管理
class ExternalDependencyManager {
  constructor() {
    this.externalLibs = new Map();
    this.cdnBaseUrl = 'https://cdn.jsdelivr.net/npm/';
    this.localLibs = new Map();
    this.init();
  }

  init() {
    // 配置外部化库
    this.registerExternalLib('react', {
      version: '18.2.0',
      global: 'React',
      cdn: `${this.cdnBaseUrl}react@18.2.0/umd/react.production.min.js`,
      local: '/libs/react.min.js'
    });

    this.registerExternalLib('react-dom', {
      version: '18.2.0',
      global: 'ReactDOM',
      cdn: `${this.cdnBaseUrl}react-dom@18.2.0/umd/react-dom.production.min.js`,
      local: '/libs/react-dom.min.js',
      dependencies: ['react']
    });

    this.registerExternalLib('lodash', {
      version: '4.17.21',
      global: '_',
      cdn: `${this.cdnBaseUrl}lodash@4.17.21/lodash.min.js`,
      local: '/libs/lodash.min.js'
    });
  }

  // 注册外部化库
  registerExternalLib(name, config) {
    this.externalLibs.set(name, {
      ...config,
      loaded: false,
      loading: false
    });
  }

  // 加载外部化依赖
  async loadExternalDependency(name, useLocal = false) {
    const libConfig = this.externalLibs.get(name);
    
    if (!libConfig) {
      throw new Error(`未知的外部依赖: ${name}`);
    }

    if (libConfig.loaded) {
      return window[libConfig.global];
    }

    if (libConfig.loading) {
      // 等待加载完成
      return new Promise((resolve) => {
        const checkLoaded = () => {
          if (libConfig.loaded) {
            resolve(window[libConfig.global]);
          } else {
            setTimeout(checkLoaded, 100);
          }
        };
        checkLoaded();
      });
    }

    libConfig.loading = true;

    try {
      // 先加载依赖
      if (libConfig.dependencies) {
        await Promise.all(
          libConfig.dependencies.map(dep => this.loadExternalDependency(dep, useLocal))
        );
      }

      // 加载主库
      const url = useLocal ? libConfig.local : libConfig.cdn;
      await this.loadScript(url);

      // 验证全局变量
      if (!window[libConfig.global]) {
        throw new Error(`全局变量 ${libConfig.global} 未找到`);
      }

      libConfig.loaded = true;
      libConfig.loading = false;

      console.log(`外部依赖加载成功: ${name}`);
      return window[libConfig.global];

    } catch (error) {
      libConfig.loading = false;
      console.error(`外部依赖加载失败: ${name}`, error);
      throw error;
    }
  }

  // 加载脚本
  loadScript(src) {
    return new Promise((resolve, reject) => {
      // 检查是否已经加载
      const existingScript = document.querySelector(`script[src="${src}"]`);
      if (existingScript) {
        resolve();
        return;
      }

      const script = document.createElement('script');
      script.src = src;
      script.async = true;
      
      script.onload = () => {
        console.log(`脚本加载成功: ${src}`);
        resolve();
      };
      
      script.onerror = () => {
        console.error(`脚本加载失败: ${src}`);
        reject(new Error(`Failed to load script: ${src}`));
      };

      document.head.appendChild(script);
    });
  }

  // 批量加载依赖
  async loadDependencies(dependencies) {
    const loadPromises = dependencies.map(dep => {
      const config = typeof dep === 'string' ? { name: dep } : dep;
      return this.loadExternalDependency(config.name, config.useLocal);
    });

    return Promise.all(loadPromises);
  }

  // 获取Webpack externals配置
  getWebpackExternals() {
    const externals = {};
    
    this.externalLibs.forEach((config, name) => {
      externals[name] = config.global;
    });

    return externals;
  }

  // 生成HTML模板中的依赖标签
  generateDependencyTags(dependencies, useLocal = false) {
    const tags = [];
    const processed = new Set();

    const addDependency = (name) => {
      if (processed.has(name)) return;
      
      const config = this.externalLibs.get(name);
      if (!config) return;

      // 先添加依赖的依赖
      if (config.dependencies) {
        config.dependencies.forEach(addDependency);
      }

      const src = useLocal ? config.local : config.cdn;
      tags.push(`<script src="${src}"></script>`);
      processed.add(name);
    };

    dependencies.forEach(addDependency);
    return tags.join('\n');
  }

  // 依赖分析
  analyzeDependencies() {
    const analysis = {
      total: this.externalLibs.size,
      loaded: 0,
      failed: 0,
      dependencies: []
    };

    this.externalLibs.forEach((config, name) => {
      const depInfo = {
        name,
        version: config.version,
        global: config.global,
        loaded: config.loaded,
        size: 0,
        dependencies: config.dependencies || []
      };

      if (config.loaded) {
        analysis.loaded++;
        depInfo.size = this.estimateLibSize(window[config.global]);
      }

      analysis.dependencies.push(depInfo);
    });

    return analysis;
  }

  // 估算库大小
  estimateLibSize(lib) {
    if (!lib) return 0;

    try {
      // 简单的大小估算
      const keys = Object.keys(lib);
      return keys.length * 100; // 粗略估算
    } catch {
      return 0;
    }
  }
}

// Webpack配置生成
function generateWebpackConfig(dependencyManager) {
  return {
    externals: dependencyManager.getWebpackExternals(),
    plugins: [
      new (class DependencyInjectionPlugin {
        apply(compiler) {
          compiler.hooks.compilation.tap('DependencyInjectionPlugin', (compilation) => {
            compilation.hooks.htmlWebpackPluginBeforeHtmlGeneration.tapAsync(
              'DependencyInjectionPlugin',
              (data, cb) => {
                const dependencies = ['react', 'react-dom', 'lodash'];
                const dependencyTags = dependencyManager.generateDependencyTags(dependencies);
                data.assets.js.unshift(...dependencyTags.split('\n'));
                cb(null, data);
              }
            );
          });
        }
      })()
    ]
  };
}

// 使用示例
const externalManager = new ExternalDependencyManager();

// 在应用启动前加载依赖
async function initializeApp() {
  try {
    await externalManager.loadDependencies(['react', 'react-dom']);
    
    // 现在可以安全使用React
    const { createElement } = window.React;
    const { render } = window.ReactDOM;
    
    const app = createElement('div', null, 'Hello from external React!');
    render(app, document.getElementById('root'));
    
  } catch (error) {
    console.error('应用初始化失败:', error);
  }
}

3.2 依赖管理方案对比

javascript 复制代码
// 依赖管理方案对比
const dependencyManagementComparison = {
  'Module Federation': {
    description: 'Webpack 5原生模块联邦',
    advantages: [
      '运行时共享',
      '版本协商',
      '类型安全',
      '构建时优化'
    ],
    disadvantages: [
      '仅支持Webpack 5',
      '配置复杂',
      '学习成本高'
    ],
    implementation: `
      // 主应用配置
      new ModuleFederationPlugin({
        shared: {
          react: { singleton: true },
          'react-dom': { singleton: true }
        }
      })
    `,
    performance: '★★★★☆',
    complexity: '★★★★☆',
    compatibility: '★★★☆☆'
  },

  'SystemJS': {
    description: '动态模块加载器',
    advantages: [
      '运行时加载',
      '框架无关',
      '灵活配置',
      '良好兼容性'
    ],
    disadvantages: [
      '运行时开销',
      '调试困难',
      '类型推断差'
    ],
    implementation: `
      System.config({
        map: {
          'react': '/shared/react.js'
        }
      });
      await System.import('react');
    `,
    performance: '★★★☆☆',
    complexity: '★★★☆☆',
    compatibility: '★★★★★'
  },

  'Externals': {
    description: 'Webpack外部化依赖',
    advantages: [
      '简单配置',
      'CDN支持',
      '缓存友好',
      '体积优化'
    ],
    disadvantages: [
      '版本管理复杂',
      '运行时风险',
      '依赖顺序'
    ],
    implementation: `
      // webpack.config.js
      module.exports = {
        externals: {
          'react': 'React',
          'react-dom': 'ReactDOM'
        }
      };
    `,
    performance: '★★★★★',
    complexity: '★★☆☆☆',
    compatibility: '★★★★☆'
  },

  'UMD Bundle': {
    description: 'UMD格式依赖包',
    advantages: [
      '通用格式',
      '简单使用',
      '良好兼容',
      '调试友好'
    ],
    disadvantages: [
      '体积较大',
      '版本冲突',
      '重复加载'
    ],
    implementation: `
      // 直接引入UMD包
      <script src="/libs/react.umd.js"></script>
      <script src="/libs/react-dom.umd.js"></script>
    `,
    performance: '★★★☆☆',
    complexity: '★★☆☆☆',
    compatibility: '★★★★★'
  }
};

3.3 依赖管理最佳实践

javascript 复制代码
// 依赖管理最佳实践实现
class BestPracticeDependencyManager {
  constructor() {
    this.dependencyStrategy = this.determineBestStrategy();
    this.manager = this.createManager();
    this.monitor = new DependencyMonitor();
  }

  // 确定最佳策略
  determineBestStrategy() {
    const environment = {
      webpackVersion: this.getWebpackVersion(),
      browserSupport: this.getBrowserSupport(),
      projectComplexity: this.getProjectComplexity(),
      performanceRequirement: this.getPerformanceRequirement()
    };

    // 策略选择逻辑
    if (environment.webpackVersion >= 5 && environment.projectComplexity === 'high') {
      return 'module-federation';
    } else if (environment.performanceRequirement === 'high') {
      return 'externals';
    } else if (environment.browserSupport === 'legacy') {
      return 'systemjs';
    } else {
      return 'hybrid'; // 混合策略
    }
  }

  // 创建对应的管理器
  createManager() {
    switch (this.dependencyStrategy) {
      case 'module-federation':
        return new ModuleFederationManager();
      case 'externals':
        return new ExternalDependencyManager();
      case 'systemjs':
        return new SystemJSDependencyManager();
      case 'hybrid':
        return new HybridDependencyManager();
      default:
        throw new Error(`Unsupported strategy: ${this.dependencyStrategy}`);
    }
  }

  // 统一的依赖加载接口
  async loadDependencies(dependencies) {
    const startTime = performance.now();
    
    try {
      const result = await this.manager.loadDependencies(dependencies);
      
      // 记录性能指标
      const loadTime = performance.now() - startTime;
      this.monitor.recordLoad(dependencies, loadTime, true);
      
      return result;
    } catch (error) {
      const loadTime = performance.now() - startTime;
      this.monitor.recordLoad(dependencies, loadTime, false);
      throw error;
    }
  }

  // 获取依赖分析报告
  getDependencyReport() {
    return {
      strategy: this.dependencyStrategy,
      metrics: this.monitor.getMetrics(),
      recommendations: this.generateRecommendations()
    };
  }

  generateRecommendations() {
    const metrics = this.monitor.getMetrics();
    const recommendations = [];

    if (metrics.averageLoadTime > 2000) {
      recommendations.push('考虑使用CDN加速依赖加载');
    }

    if (metrics.failureRate > 0.1) {
      recommendations.push('检查依赖的可用性和版本兼容性');
    }

    if (metrics.duplicateLoads > 5) {
      recommendations.push('优化依赖加载策略,减少重复加载');
    }

    return recommendations;
  }
}

// 依赖监控器
class DependencyMonitor {
  constructor() {
    this.loadHistory = [];
    this.metrics = {
      totalLoads: 0,
      successfulLoads: 0,
      failedLoads: 0,
      totalLoadTime: 0,
      duplicateLoads: 0
    };
  }

  recordLoad(dependencies, loadTime, success) {
    const record = {
      dependencies,
      loadTime,
      success,
      timestamp: Date.now()
    };

    this.loadHistory.push(record);
    this.updateMetrics(record);
  }

  updateMetrics(record) {
    this.metrics.totalLoads++;
    this.metrics.totalLoadTime += record.loadTime;

    if (record.success) {
      this.metrics.successfulLoads++;
    } else {
      this.metrics.failedLoads++;
    }

    // 检测重复加载
    const similarLoads = this.loadHistory.filter(h => 
      h !== record && 
      JSON.stringify(h.dependencies) === JSON.stringify(record.dependencies) &&
      Math.abs(h.timestamp - record.timestamp) < 60000 // 1分钟内
    );

    if (similarLoads.length > 0) {
      this.metrics.duplicateLoads++;
    }
  }

  getMetrics() {
    return {
      ...this.metrics,
      averageLoadTime: this.metrics.totalLoadTime / this.metrics.totalLoads,
      successRate: this.metrics.successfulLoads / this.metrics.totalLoads,
      failureRate: this.metrics.failedLoads / this.metrics.totalLoads
    };
  }
}

3.4 依赖管理流程图

graph TD A[开始依赖管理] --> B[分析项目需求] B --> C{Webpack版本} C -->|5.x| D{项目复杂度} C -->|4.x及以下| E{性能要求} D -->|高| F[Module Federation] D -->|中低| G{兼容性需求} E -->|高| H[Externals方案] E -->|一般| I[SystemJS方案] G -->|现代浏览器| J[ES Modules] G -->|兼容IE| K[UMD方案] F --> L[配置模块联邦] H --> M[配置外部化依赖] I --> N[配置SystemJS] J --> O[配置ES模块] K --> P[配置UMD包] L --> Q[依赖版本协商] M --> R[CDN资源管理] N --> S[动态模块加载] O --> T[原生模块导入] P --> U[全局变量管理] Q --> V[依赖管理完成] R --> V S --> V T --> V U --> V style F fill:#e8f5e8 style H fill:#e3f2fd style I fill:#fff3e0 style J fill:#f3e5f5 style K fill:#fce4ec

4. 路由状态更新机制对比

路由状态同步是微前端架构中确保用户体验一致性的关键环节。

4.1 路由同步策略

主从路由模式

主应用控制整体路由,子应用遵循主应用的路由规则。

javascript 复制代码
// 主从路由管理器
class MasterSlaveRouterManager {
  constructor() {
    this.masterRouter = null;
    this.slaveRouters = new Map();
    this.routeListeners = new Set();
    this.currentRoute = null;
    this.routeHistory = [];
    this.init();
  }

  init() {
    // 监听浏览器路由变化
    window.addEventListener('popstate', this.handlePopState.bind(this));
    window.addEventListener('pushstate', this.handlePushState.bind(this));
    window.addEventListener('replacestate', this.handleReplaceState.bind(this));
    
    // 劫持原生路由方法
    this.hijackNativeRouter();
  }

  // 劫持原生路由方法
  hijackNativeRouter() {
    const originalPushState = history.pushState;
    const originalReplaceState = history.replaceState;

    history.pushState = (...args) => {
      originalPushState.apply(history, args);
      this.handleRouteChange('push', args[2]);
    };

    history.replaceState = (...args) => {
      originalReplaceState.apply(history, args);
      this.handleRouteChange('replace', args[2]);
    };
  }

  // 注册主路由器
  registerMasterRouter(router) {
    this.masterRouter = router;
    console.log('主路由器已注册');
  }

  // 注册从路由器
  registerSlaveRouter(appName, router) {
    this.slaveRouters.set(appName, {
      router,
      active: false,
      basePath: this.getAppBasePath(appName),
      routes: this.extractRoutes(router)
    });
    
    console.log(`从路由器已注册: ${appName}`);
  }

  // 处理路由变化
  handleRouteChange(type, url) {
    const newRoute = {
      path: url || location.pathname,
      search: location.search,
      hash: location.hash,
      fullPath: location.href,
      timestamp: Date.now(),
      type
    };

    // 更新当前路由
    this.currentRoute = newRoute;
    this.routeHistory.push(newRoute);

    // 确定目标应用
    const targetApp = this.getTargetApp(newRoute.path);
    
    // 同步到子应用
    this.syncToSlaveRouters(newRoute, targetApp);
    
    // 通知监听器
    this.notifyRouteChange(newRoute);
  }

  // 获取目标应用
  getTargetApp(path) {
    for (const [appName, slaveRouter] of this.slaveRouters) {
      if (path.startsWith(slaveRouter.basePath)) {
        return appName;
      }
    }
    return null;
  }

  // 同步到从路由器
  syncToSlaveRouters(route, activeApp) {
    this.slaveRouters.forEach((slaveRouter, appName) => {
      const shouldActivate = appName === activeApp;
      
      if (shouldActivate && !slaveRouter.active) {
        // 激活应用路由
        this.activateSlaveRouter(appName, route);
      } else if (!shouldActivate && slaveRouter.active) {
        // 失活应用路由
        this.deactivateSlaveRouter(appName);
      } else if (shouldActivate && slaveRouter.active) {
        // 更新应用路由
        this.updateSlaveRouter(appName, route);
      }
    });
  }

  // 激活从路由器
  activateSlaveRouter(appName, route) {
    const slaveRouter = this.slaveRouters.get(appName);
    if (!slaveRouter) return;

    slaveRouter.active = true;
    
    // 计算应用内路由路径
    const appPath = route.path.replace(slaveRouter.basePath, '') || '/';
    
    // 通知应用路由变化
    if (slaveRouter.router && slaveRouter.router.push) {
      slaveRouter.router.push({
        path: appPath,
        search: route.search,
        hash: route.hash
      });
    }

    console.log(`激活从路由器: ${appName}, 路径: ${appPath}`);
  }

  // 失活从路由器
  deactivateSlaveRouter(appName) {
    const slaveRouter = this.slaveRouters.get(appName);
    if (!slaveRouter) return;

    slaveRouter.active = false;
    
    // 通知应用路由失活
    if (slaveRouter.router && slaveRouter.router.onDeactivate) {
      slaveRouter.router.onDeactivate();
    }

    console.log(`失活从路由器: ${appName}`);
  }

  // 更新从路由器
  updateSlaveRouter(appName, route) {
    const slaveRouter = this.slaveRouters.get(appName);
    if (!slaveRouter) return;

    const appPath = route.path.replace(slaveRouter.basePath, '') || '/';
    
    // 检查路由是否真的发生了变化
    if (slaveRouter.currentPath !== appPath) {
      slaveRouter.currentPath = appPath;
      
      if (slaveRouter.router && slaveRouter.router.replace) {
        slaveRouter.router.replace({
          path: appPath,
          search: route.search,
          hash: route.hash
        });
      }
    }
  }

  // 从子应用触发路由跳转
  navigateFromSlave(appName, path, options = {}) {
    const slaveRouter = this.slaveRouters.get(appName);
    if (!slaveRouter) {
      console.warn(`未找到从路由器: ${appName}`);
      return;
    }

    // 构造完整路径
    const fullPath = slaveRouter.basePath + path.replace(/^\//, '');
    
    // 使用主路由器进行导航
    if (options.replace) {
      history.replaceState(null, '', fullPath);
    } else {
      history.pushState(null, '', fullPath);
    }
  }

  // 添加路由监听器
  addRouteListener(listener) {
    this.routeListeners.add(listener);
    
    return () => {
      this.routeListeners.delete(listener);
    };
  }

  // 通知路由变化
  notifyRouteChange(route) {
    this.routeListeners.forEach(listener => {
      try {
        listener(route);
      } catch (error) {
        console.error('路由监听器执行失败:', error);
      }
    });
  }

  // 获取应用基础路径
  getAppBasePath(appName) {
    // 根据应用名生成基础路径
    return `/${appName}`;
  }

  // 提取路由配置
  extractRoutes(router) {
    // 这里需要根据具体的路由器实现来提取路由信息
    if (router && router.getRoutes) {
      return router.getRoutes();
    }
    return [];
  }

  // 处理浏览器后退/前进
  handlePopState(event) {
    this.handleRouteChange('pop', location.pathname);
  }

  handlePushState(event) {
    this.handleRouteChange('push', event.detail?.url);
  }

  handleReplaceState(event) {
    this.handleRouteChange('replace', event.detail?.url);
  }

  // 获取路由统计信息
  getRouteStats() {
    return {
      totalRoutes: this.routeHistory.length,
      activeApps: Array.from(this.slaveRouters.entries())
        .filter(([name, router]) => router.active)
        .map(([name]) => name),
      currentRoute: this.currentRoute,
      registeredApps: Array.from(this.slaveRouters.keys())
    };
  }
}

// 使用示例
const routerManager = new MasterSlaveRouterManager();

// 在主应用中注册
const mainRouter = new VueRouter({
  routes: [
    { path: '/home', component: Home },
    { path: '/micro-app-1/*', component: MicroAppContainer }
  ]
});

routerManager.registerMasterRouter(mainRouter);

// 在子应用中注册
const microAppRouter = new VueRouter({
  routes: [
    { path: '/', component: MicroHome },
    { path: '/detail', component: MicroDetail }
  ]
});

routerManager.registerSlaveRouter('micro-app-1', microAppRouter);

// 监听路由变化
routerManager.addRouteListener((route) => {
  console.log('路由变化:', route);
  updateBreadcrumb(route);
  trackPageView(route);
});
事件驱动路由

通过事件机制实现路由状态的双向同步。

javascript 复制代码
// 事件驱动路由管理器
class EventDrivenRouterManager {
  constructor() {
    this.eventBus = new EventTarget();
    this.routerInstances = new Map();
    this.routeState = {
      current: null,
      previous: null,
      pending: null
    };
    this.navigationGuards = [];
    this.init();
  }

  init() {
    // 监听浏览器路由事件
    window.addEventListener('popstate', this.handleBrowserNavigation.bind(this));
    
    // 设置全局路由事件监听
    this.setupGlobalRouteEvents();
  }

  // 设置全局路由事件
  setupGlobalRouteEvents() {
    // 监听路由导航请求
    this.eventBus.addEventListener('route:navigate', this.handleNavigationRequest.bind(this));
    
    // 监听路由状态更新
    this.eventBus.addEventListener('route:update', this.handleRouteUpdate.bind(this));
    
    // 监听应用路由注册
    this.eventBus.addEventListener('app:register-router', this.handleRouterRegistration.bind(this));
  }

  // 注册应用路由器
  registerRouter(appName, router, config = {}) {
    const routerInstance = {
      name: appName,
      router,
      config: {
        basePath: config.basePath || `/${appName}`,
        mode: config.mode || 'history',
        beforeEach: config.beforeEach,
        afterEach: config.afterEach,
        ...config
      },
      active: false,
      lastRoute: null
    };

    this.routerInstances.set(appName, routerInstance);

    // 包装路由器的导航方法
    this.wrapRouterMethods(routerInstance);

    // 触发注册事件
    this.eventBus.dispatchEvent(new CustomEvent('app:register-router', {
      detail: { appName, config: routerInstance.config }
    }));

    console.log(`路由器注册成功: ${appName}`);
  }

  // 包装路由器方法
  wrapRouterMethods(routerInstance) {
    const { router, name } = routerInstance;

    // 包装push方法
    if (router.push) {
      const originalPush = router.push.bind(router);
      router.push = (location) => {
        this.beforeRouterNavigation(name, location, 'push');
        return originalPush(location).then(() => {
          this.afterRouterNavigation(name, location, 'push');
        });
      };
    }

    // 包装replace方法
    if (router.replace) {
      const originalReplace = router.replace.bind(router);
      router.replace = (location) => {
        this.beforeRouterNavigation(name, location, 'replace');
        return originalReplace(location).then(() => {
          this.afterRouterNavigation(name, location, 'replace');
        });
      };
    }

    // 监听路由变化
    if (router.beforeEach) {
      router.beforeEach((to, from, next) => {
        this.handleAppRouteChange(name, to, from, next);
      });
    }
  }

  // 路由导航前处理
  beforeRouterNavigation(appName, location, type) {
    const event = new CustomEvent('route:before-navigate', {
      detail: { appName, location, type }
    });
    this.eventBus.dispatchEvent(event);
  }

  // 路由导航后处理
  afterRouterNavigation(appName, location, type) {
    const event = new CustomEvent('route:after-navigate', {
      detail: { appName, location, type }
    });
    this.eventBus.dispatchEvent(event);
  }

  // 处理应用内路由变化
  handleAppRouteChange(appName, to, from, next) {
    const routerInstance = this.routerInstances.get(appName);
    if (!routerInstance) {
      next();
      return;
    }

    // 构造全局路由路径
    const globalPath = routerInstance.config.basePath + to.path.replace(/^\//, '');
    
    // 更新浏览器URL
    if (window.location.pathname !== globalPath) {
      history.pushState(null, '', globalPath + (to.query ? '?' + new URLSearchParams(to.query).toString() : ''));
    }

    // 更新路由状态
    this.updateRouteState({
      path: globalPath,
      appName,
      appRoute: to,
      fullPath: globalPath + (location.search || '') + (location.hash || '')
    });

    next();
  }

  // 处理导航请求
  async handleNavigationRequest(event) {
    const { path, options = {} } = event.detail;
    
    try {
      // 执行导航守卫
      await this.executeNavigationGuards(path, options);
      
      // 执行导航
      await this.performNavigation(path, options);
      
    } catch (error) {
      console.error('导航失败:', error);
      
      // 触发导航失败事件
      this.eventBus.dispatchEvent(new CustomEvent('route:navigate-failed', {
        detail: { path, options, error }
      }));
    }
  }

  // 执行导航守卫
  async executeNavigationGuards(path, options) {
    for (const guard of this.navigationGuards) {
      const result = await guard(path, this.routeState.current, options);
      if (result === false) {
        throw new Error('Navigation cancelled by guard');
      } else if (typeof result === 'string') {
        // 重定向
        throw new Error(`Redirect to: ${result}`);
      }
    }
  }

  // 执行导航
  async performNavigation(path, options) {
    // 找到目标应用
    const targetApp = this.findTargetApp(path);
    
    if (!targetApp) {
      throw new Error(`No app found for path: ${path}`);
    }

    const routerInstance = this.routerInstances.get(targetApp);
    const appPath = path.replace(routerInstance.config.basePath, '') || '/';

    // 激活目标应用
    await this.activateApp(targetApp);

    // 在应用内导航
    if (routerInstance.router.push) {
      if (options.replace) {
        await routerInstance.router.replace(appPath);
      } else {
        await routerInstance.router.push(appPath);
      }
    }
  }

  // 激活应用
  async activateApp(appName) {
    // 失活其他应用
    for (const [name, instance] of this.routerInstances) {
      if (name !== appName && instance.active) {
        instance.active = false;
        
        // 触发应用失活事件
        this.eventBus.dispatchEvent(new CustomEvent('app:deactivated', {
          detail: { appName: name }
        }));
      }
    }

    // 激活目标应用
    const targetInstance = this.routerInstances.get(appName);
    if (targetInstance) {
      targetInstance.active = true;
      
      // 触发应用激活事件
      this.eventBus.dispatchEvent(new CustomEvent('app:activated', {
        detail: { appName }
      }));
    }
  }

  // 查找目标应用
  findTargetApp(path) {
    for (const [appName, instance] of this.routerInstances) {
      if (path.startsWith(instance.config.basePath)) {
        return appName;
      }
    }
    return null;
  }

  // 更新路由状态
  updateRouteState(newRoute) {
    this.routeState.previous = this.routeState.current;
    this.routeState.current = newRoute;

    // 触发路由状态更新事件
    this.eventBus.dispatchEvent(new CustomEvent('route:state-updated', {
      detail: {
        current: this.routeState.current,
        previous: this.routeState.previous
      }
    }));
  }

  // 添加导航守卫
  addNavigationGuard(guard) {
    this.navigationGuards.push(guard);
    
    return () => {
      const index = this.navigationGuards.indexOf(guard);
      if (index > -1) {
        this.navigationGuards.splice(index, 1);
      }
    };
  }

  // 程序化导航
  push(path, options = {}) {
    this.eventBus.dispatchEvent(new CustomEvent('route:navigate', {
      detail: { path, options: { ...options, replace: false } }
    }));
  }

  replace(path, options = {}) {
    this.eventBus.dispatchEvent(new CustomEvent('route:navigate', {
      detail: { path, options: { ...options, replace: true } }
    }));
  }

  // 处理浏览器导航
  handleBrowserNavigation(event) {
    const path = location.pathname;
    const targetApp = this.findTargetApp(path);
    
    if (targetApp) {
      this.performNavigation(path, { fromBrowser: true });
    }
  }

  // 获取路由状态
  getRouteState() {
    return { ...this.routeState };
  }

  // 监听路由事件
  onRouteChange(callback) {
    this.eventBus.addEventListener('route:state-updated', callback);
    
    return () => {
      this.eventBus.removeEventListener('route:state-updated', callback);
    };
  }
}

// 使用示例
const eventRouterManager = new EventDrivenRouterManager();

// 注册导航守卫
eventRouterManager.addNavigationGuard(async (to, from, options) => {
  console.log('导航守卫:', { to, from, options });
  
  // 权限检查
  if (to.includes('/admin') && !isAdmin()) {
    return '/login';
  }
  
  // 数据预加载
  if (to.includes('/dashboard')) {
    await preloadDashboardData();
  }
  
  return true;
});

// 监听路由变化
eventRouterManager.onRouteChange((event) => {
  const { current, previous } = event.detail;
  console.log('路由状态更新:', { current, previous });
  
  // 更新面包屑
  updateBreadcrumb(current);
  
  // 页面统计
  trackPageView(current);
});

// 注册应用路由器
eventRouterManager.registerRouter('micro-app-1', microAppRouter, {
  basePath: '/micro-app-1',
  beforeEach: (to, from, next) => {
    console.log('micro-app-1 路由变化:', { to, from });
    next();
  }
});

// 程序化导航
eventRouterManager.push('/micro-app-1/dashboard');

4.2 路由状态同步流程图

graph TD A[路由变化触发] --> B{变化来源} B -->|浏览器| C[popstate事件] B -->|应用内| D[路由器导航] B -->|程序化| E[API调用] C --> F[解析目标路径] D --> F E --> F F --> G[确定目标应用] G --> H{目标应用存在?} H -->|否| I[404处理] H -->|是| J[执行导航守卫] J --> K{守卫通过?} K -->|否| L[阻止导航] K -->|是| M[应用切换处理] M --> N[失活当前应用] N --> O[激活目标应用] O --> P[同步应用路由] P --> Q[更新浏览器URL] Q --> R[触发状态更新事件] R --> S[路由同步完成] I --> T[显示错误页面] L --> U[保持当前状态] style J fill:#e8f5e8 style M fill:#e3f2fd style R fill:#fff3e0 style I fill:#ffcdd2 style L fill:#ffcdd2

5. 通信方式全面对比

微前端应用间的通信是确保系统协调工作的核心机制。

5.1 通信方式分类对比

基于事件的通信
javascript 复制代码
// 事件通信对比实现
const eventCommunicationComparison = {
  // 自定义事件
  'Custom Events': {
    description: '基于DOM自定义事件的通信',
    implementation: `
      // 发送方
      window.dispatchEvent(new CustomEvent('micro:userLogin', {
        detail: { userId: 123, username: 'john' }
      }));
      
      // 接收方
      window.addEventListener('micro:userLogin', (event) => {
        console.log('用户登录:', event.detail);
      });
    `,
    pros: ['原生支持', '简单易用', '无依赖'],
    cons: ['全局污染', '难以管理', '无类型检查'],
    scenario: '简单的事件通知',
    performance: '★★★★★'
  },

  // EventBus
  'Event Bus': {
    description: '专用的事件总线系统',
    implementation: `
      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('userLogin', handleUserLogin);
      eventBus.emit('userLogin', userData);
    `,
    pros: ['集中管理', '支持取消监听', '可扩展'],
    cons: ['需要实现', '内存泄漏风险', '调试困难'],
    scenario: '复杂的事件交互',
    performance: '★★★★☆'
  },

  // Pub/Sub
  'Pub/Sub Pattern': {
    description: '发布订阅模式通信',
    implementation: `
      class PubSub {
        constructor() {
          this.subscribers = new Map();
        }
        
        subscribe(topic, callback) {
          if (!this.subscribers.has(topic)) {
            this.subscribers.set(topic, new Set());
          }
          this.subscribers.get(topic).add(callback);
          
          return () => this.subscribers.get(topic).delete(callback);
        }
        
        publish(topic, data) {
          const callbacks = this.subscribers.get(topic);
          if (callbacks) {
            callbacks.forEach(callback => {
              try {
                callback(data);
              } catch (error) {
                console.error('Pub/Sub callback error:', error);
              }
            });
          }
        }
      }
    `,
    pros: ['解耦性好', '支持多订阅', '错误隔离'],
    cons: ['复杂度高', '调试困难', '性能开销'],
    scenario: '松耦合的系统通信',
    performance: '★★★☆☆'
  }
};
基于状态的通信
javascript 复制代码
// 状态通信对比实现
const stateCommunicationComparison = {
  // 全局状态
  'Global State': {
    description: '全局状态管理器',
    implementation: `
      class GlobalStateManager {
        constructor() {
          this.state = {};
          this.listeners = new Map();
        }
        
        setState(key, value) {
          const oldValue = this.state[key];
          this.state[key] = value;
          
          const keyListeners = this.listeners.get(key);
          if (keyListeners) {
            keyListeners.forEach(callback => callback(value, oldValue));
          }
        }
        
        getState(key) {
          return this.state[key];
        }
        
        subscribe(key, callback) {
          if (!this.listeners.has(key)) {
            this.listeners.set(key, new Set());
          }
          this.listeners.get(key).add(callback);
          
          // 立即调用一次
          callback(this.state[key], undefined);
          
          return () => this.listeners.get(key).delete(callback);
        }
      }
      
      const globalState = new GlobalStateManager();
      
      // 应用A
      globalState.setState('user', { id: 1, name: 'John' });
      
      // 应用B
      const unsubscribe = globalState.subscribe('user', (user) => {
        console.log('用户状态更新:', user);
      });
    `,
    pros: ['状态持久', '自动通知', '类型安全'],
    cons: ['全局污染', '状态冲突', '难以调试'],
    scenario: '需要持久化状态的场景',
    performance: '★★★★☆'
  },

  // Redux/Vuex
  'Store Pattern': {
    description: '基于Store模式的状态管理',
    implementation: `
      // 简化的Store实现
      class MicroFrontendStore {
        constructor() {
          this.state = {};
          this.reducers = {};
          this.middlewares = [];
          this.subscribers = new Set();
        }
        
        registerReducer(namespace, reducer) {
          this.reducers[namespace] = reducer;
          if (!this.state[namespace]) {
            this.state[namespace] = {};
          }
        }
        
        dispatch(action) {
          const newState = { ...this.state };
          
          Object.keys(this.reducers).forEach(namespace => {
            newState[namespace] = this.reducers[namespace](
              this.state[namespace], 
              action
            );
          });
          
          // 应用中间件
          this.middlewares.forEach(middleware => {
            middleware(action, this.state, newState);
          });
          
          this.state = newState;
          
          // 通知订阅者
          this.subscribers.forEach(callback => callback(this.state));
        }
        
        subscribe(callback) {
          this.subscribers.add(callback);
          return () => this.subscribers.delete(callback);
        }
        
        getState() {
          return this.state;
        }
      }
      
      const store = new MicroFrontendStore();
      
      // 注册reducer
      store.registerReducer('user', (state = {}, action) => {
        switch (action.type) {
          case 'SET_USER':
            return { ...state, ...action.payload };
          default:
            return state;
        }
      });
      
      // 订阅状态变化
      store.subscribe((state) => {
        console.log('Store状态更新:', state);
      });
      
      // 分发action
      store.dispatch({
        type: 'SET_USER',
        payload: { id: 1, name: 'John' }
      });
    `,
    pros: ['可预测性', '时间旅行', '中间件支持'],
    cons: ['学习成本', '样板代码', '性能开销'],
    scenario: '复杂的状态管理需求',
    performance: '★★★☆☆'
  },

  // 响应式状态
  'Reactive State': {
    description: '基于响应式编程的状态管理',
    implementation: `
      class ReactiveState {
        constructor() {
          this.state = this.createReactiveState({});
          this.effects = new Set();
        }
        
        createReactiveState(target) {
          return new Proxy(target, {
            set: (obj, prop, value) => {
              const oldValue = obj[prop];
              obj[prop] = value;
              
              // 触发副作用
              this.effects.forEach(effect => {
                if (effect.dependencies.has(prop)) {
                  effect.callback(value, oldValue, prop);
                }
              });
              
              return true;
            },
            
            get: (obj, prop) => {
              // 收集依赖
              if (this.currentEffect) {
                this.currentEffect.dependencies.add(prop);
              }
              return obj[prop];
            }
          });
        }
        
        effect(callback) {
          const effect = {
            callback,
            dependencies: new Set()
          };
          
          this.currentEffect = effect;
          callback(); // 首次执行收集依赖
          this.currentEffect = null;
          
          this.effects.add(effect);
          
          return () => this.effects.delete(effect);
        }
        
        computed(fn) {
          let cached = null;
          let dirty = true;
          
          const computedEffect = {
            callback: () => {
              dirty = true;
            },
            dependencies: new Set()
          };
          
          this.effects.add(computedEffect);
          
          return () => {
            if (dirty) {
              this.currentEffect = computedEffect;
              cached = fn();
              this.currentEffect = null;
              dirty = false;
            }
            return cached;
          };
        }
      }
      
      const reactiveState = new ReactiveState();
      
      // 定义响应式状态
      reactiveState.state.user = { name: 'John', age: 25 };
      
      // 创建副作用
      reactiveState.effect(() => {
        console.log('用户姓名:', reactiveState.state.user.name);
      });
      
      // 创建计算属性
      const userDisplayName = reactiveState.computed(() => {
        return \`\${reactiveState.state.user.name} (\${reactiveState.state.user.age})\`;
      });
      
      // 状态变更会自动触发副作用
      reactiveState.state.user.name = 'Jane';
    `,
    pros: ['自动依赖收集', '细粒度更新', '直观易用'],
    cons: ['实现复杂', '调试困难', '内存开销'],
    scenario: '需要细粒度响应的应用',
    performance: '★★★★☆'
  }
};
基于消息的通信
javascript 复制代码
// 消息通信对比实现
const messageCommunicationComparison = {
  // PostMessage
  'PostMessage': {
    description: '浏览器原生的跨域消息通信',
    implementation: `
      // 主应用
      class PostMessageCommunicator {
        constructor() {
          this.messageHandlers = new Map();
          this.init();
        }
        
        init() {
          window.addEventListener('message', this.handleMessage.bind(this));
        }
        
        sendToApp(appName, data) {
          const iframe = document.querySelector(\`iframe[data-app="\${appName}"]\`);
          if (iframe && iframe.contentWindow) {
            iframe.contentWindow.postMessage({
              type: 'main-to-app',
              appName,
              data,
              timestamp: Date.now()
            }, '*');
          }
        }
        
        handleMessage(event) {
          const { type, appName, data } = event.data;
          
          if (type === 'app-to-main') {
            const handler = this.messageHandlers.get(appName);
            if (handler) {
              handler(data);
            }
          }
        }
        
        onMessage(appName, handler) {
          this.messageHandlers.set(appName, handler);
        }
      }
      
      // 子应用
      class IframeAppCommunicator {
        constructor(appName) {
          this.appName = appName;
          this.messageHandlers = new Map();
          this.init();
        }
        
        init() {
          window.addEventListener('message', this.handleMessage.bind(this));
        }
        
        sendToMain(data) {
          window.parent.postMessage({
            type: 'app-to-main',
            appName: this.appName,
            data,
            timestamp: Date.now()
          }, '*');
        }
        
        handleMessage(event) {
          const { type, appName, data } = event.data;
          
          if (type === 'main-to-app' && appName === this.appName) {
            this.messageHandlers.forEach(handler => handler(data));
          }
        }
        
        onMessage(handler) {
          this.messageHandlers.set(Date.now(), handler);
        }
      }
    `,
    pros: ['原生支持', '跨域安全', '简单可靠'],
    cons: ['仅限iframe', '序列化限制', '单向通信'],
    scenario: 'iframe架构的微前端',
    performance: '★★★★☆'
  },

  // WebSocket
  'WebSocket': {
    description: '基于WebSocket的实时通信',
    implementation: `
      class WebSocketCommunicator {
        constructor(url) {
          this.url = url;
          this.ws = null;
          this.reconnectInterval = 5000;
          this.messageHandlers = new Map();
          this.connect();
        }
        
        connect() {
          try {
            this.ws = new WebSocket(this.url);
            
            this.ws.onopen = () => {
              console.log('WebSocket连接已建立');
            };
            
            this.ws.onmessage = (event) => {
              try {
                const message = JSON.parse(event.data);
                this.handleMessage(message);
              } catch (error) {
                console.error('消息解析失败:', error);
              }
            };
            
            this.ws.onclose = () => {
              console.log('WebSocket连接已关闭');
              setTimeout(() => this.connect(), this.reconnectInterval);
            };
            
            this.ws.onerror = (error) => {
              console.error('WebSocket错误:', error);
            };
            
          } catch (error) {
            console.error('WebSocket连接失败:', error);
            setTimeout(() => this.connect(), this.reconnectInterval);
          }
        }
        
        send(type, data) {
          if (this.ws && this.ws.readyState === WebSocket.OPEN) {
            this.ws.send(JSON.stringify({
              type,
              data,
              timestamp: Date.now(),
              sender: window.location.href
            }));
          } else {
            console.warn('WebSocket未连接');
          }
        }
        
        handleMessage(message) {
          const { type, data } = message;
          const handler = this.messageHandlers.get(type);
          
          if (handler) {
            handler(data);
          }
        }
        
        on(type, handler) {
          this.messageHandlers.set(type, handler);
        }
        
        broadcast(type, data) {
          this.send('broadcast', { type, data });
        }
        
        close() {
          if (this.ws) {
            this.ws.close();
          }
        }
      }
      
      // 使用示例
      const wsCommunicator = new WebSocketCommunicator('ws://localhost:8080');
      
      // 监听消息
      wsCommunicator.on('userStatusChange', (data) => {
        console.log('用户状态变化:', data);
      });
      
      // 发送消息
      wsCommunicator.send('userLogin', { userId: 123 });
      
      // 广播消息
      wsCommunicator.broadcast('globalNotification', {
        message: '系统维护通知'
      });
    `,
    pros: ['实时通信', '双向通信', '服务端支持'],
    cons: ['需要服务端', '连接管理', '资源消耗'],
    scenario: '需要实时同步的应用',
    performance: '★★★☆☆'
  },

  // SharedWorker
  'SharedWorker': {
    description: '基于SharedWorker的多标签页通信',
    implementation: `
      // SharedWorker脚本 (shared-worker.js)
      const connections = new Set();
      const messageQueues = new Map();
      
      self.addEventListener('connect', (event) => {
        const port = event.ports[0];
        connections.add(port);
        
        port.onmessage = (e) => {
          const { type, data, target } = e.data;
          
          switch (type) {
            case 'broadcast':
              // 广播给所有连接
              connections.forEach(conn => {
                if (conn !== port) {
                  conn.postMessage({ type: 'broadcast', data });
                }
              });
              break;
              
            case 'direct':
              // 直接发送给特定目标
              const targetPort = findPortByTarget(target);
              if (targetPort) {
                targetPort.postMessage({ type: 'direct', data });
              }
              break;
              
            case 'register':
              // 注册端口标识
              port._identifier = data.identifier;
              break;
          }
        };
        
        port.onclose = () => {
          connections.delete(port);
        };
        
        port.start();
      });
      
      function findPortByTarget(target) {
        for (const port of connections) {
          if (port._identifier === target) {
            return port;
          }
        }
        return null;
      }
      
      // 应用中的使用
      class SharedWorkerCommunicator {
        constructor(appName) {
          this.appName = appName;
          this.worker = new SharedWorker('/shared-worker.js');
          this.port = this.worker.port;
          this.messageHandlers = new Map();
          this.init();
        }
        
        init() {
          this.port.onmessage = (event) => {
            const { type, data } = event.data;
            const handler = this.messageHandlers.get(type);
            
            if (handler) {
              handler(data);
            }
          };
          
          // 注册应用标识
          this.port.postMessage({
            type: 'register',
            data: { identifier: this.appName }
          });
          
          this.port.start();
        }
        
        broadcast(data) {
          this.port.postMessage({
            type: 'broadcast',
            data: { ...data, from: this.appName }
          });
        }
        
        sendTo(target, data) {
          this.port.postMessage({
            type: 'direct',
            target,
            data: { ...data, from: this.appName }
          });
        }
        
        on(type, handler) {
          this.messageHandlers.set(type, handler);
        }
      }
      
      // 使用示例
      const sharedCommunicator = new SharedWorkerCommunicator('main-app');
      
      // 监听广播消息
      sharedCommunicator.on('broadcast', (data) => {
        console.log('收到广播:', data);
      });
      
      // 发送广播
      sharedCommunicator.broadcast({
        type: 'userLogin',
        userId: 123
      });
      
      // 发送给特定应用
      sharedCommunicator.sendTo('micro-app-1', {
        type: 'themeChange',
        theme: 'dark'
      });
    `,
    pros: ['多标签页通信', '持久连接', '共享状态'],
    cons: ['浏览器支持限制', '调试困难', '资源共享'],
    scenario: '多标签页协作的应用',
    performance: '★★★☆☆'
  }
};

5.2 通信方式选择决策树

graph TD A[开始选择通信方式] --> B{通信场景} B -->|简单事件通知| C[自定义事件] B -->|复杂状态管理| D{状态持久化需求} B -->|跨域通信| E[PostMessage] B -->|实时通信| F[WebSocket] B -->|多标签页| G[SharedWorker] D -->|需要持久化| H{状态复杂度} D -->|无需持久化| I[EventBus] H -->|简单| J[全局状态] H -->|复杂| K{框架偏好} K -->|Redux系| L[Store模式] K -->|Vue系| M[响应式状态] K -->|无偏好| N[自定义Store] C --> O[实现完成] I --> O E --> O F --> O G --> O J --> O L --> O M --> O N --> O style C fill:#e8f5e8 style I fill:#e3f2fd style J fill:#fff3e0 style L fill:#f3e5f5 style M fill:#fce4ec

5.3 通信性能对比测试

javascript 复制代码
// 通信性能测试套件
class CommunicationPerformanceTest {
  constructor() {
    this.testResults = new Map();
    this.testIterations = 1000;
  }

  // 测试自定义事件性能
  async testCustomEvents() {
    const startTime = performance.now();
    
    for (let i = 0; i < this.testIterations; i++) {
      const event = new CustomEvent('test-event', {
        detail: { iteration: i, data: 'test data' }
      });
      window.dispatchEvent(event);
    }
    
    const endTime = performance.now();
    return endTime - startTime;
  }

  // 测试EventBus性能
  async testEventBus() {
    const eventBus = new EventBus();
    const startTime = performance.now();
    
    eventBus.on('test-event', () => {});
    
    for (let i = 0; i < this.testIterations; i++) {
      eventBus.emit('test-event', { iteration: i, data: 'test data' });
    }
    
    const endTime = performance.now();
    return endTime - startTime;
  }

  // 测试状态管理性能
  async testStateManager() {
    const stateManager = new GlobalStateManager();
    const startTime = performance.now();
    
    stateManager.subscribe('testKey', () => {});
    
    for (let i = 0; i < this.testIterations; i++) {
      stateManager.setState('testKey', { iteration: i, data: 'test data' });
    }
    
    const endTime = performance.now();
    return endTime - startTime;
  }

  // 测试PostMessage性能
  async testPostMessage() {
    const iframe = document.createElement('iframe');
    iframe.src = 'about:blank';
    document.body.appendChild(iframe);
    
    const startTime = performance.now();
    
    for (let i = 0; i < this.testIterations; i++) {
      iframe.contentWindow.postMessage({
        iteration: i,
        data: 'test data'
      }, '*');
    }
    
    const endTime = performance.now();
    document.body.removeChild(iframe);
    return endTime - startTime;
  }

  // 运行完整性能测试
  async runFullPerformanceTest() {
    console.log('开始通信性能测试...');
    
    const results = {
      customEvents: await this.testCustomEvents(),
      eventBus: await this.testEventBus(),
      stateManager: await this.testStateManager(),
      postMessage: await this.testPostMessage()
    };

    // 计算相对性能
    const baseline = Math.min(...Object.values(results));
    const relativeResults = {};
    
    Object.entries(results).forEach(([method, time]) => {
      relativeResults[method] = {
        absoluteTime: time,
        relativePerformance: (baseline / time * 100).toFixed(2) + '%',
        throughput: (this.testIterations / time * 1000).toFixed(0) + ' ops/sec'
      };
    });

    return relativeResults;
  }

  // 内存使用测试
  async testMemoryUsage() {
    const initialMemory = performance.memory ? performance.memory.usedJSHeapSize : 0;
    
    // 创建大量通信实例
    const instances = [];
    for (let i = 0; i < 100; i++) {
      instances.push({
        eventBus: new EventBus(),
        stateManager: new GlobalStateManager(),
        customEventListeners: []
      });
    }

    // 注册监听器
    instances.forEach((instance, index) => {
      instance.eventBus.on('test', () => {});
      instance.stateManager.subscribe('test', () => {});
      
      const listener = () => {};
      window.addEventListener(`test-${index}`, listener);
      instance.customEventListeners.push(listener);
    });

    const peakMemory = performance.memory ? performance.memory.usedJSHeapSize : 0;

    // 清理
    instances.forEach((instance, index) => {
      instance.customEventListeners.forEach(listener => {
        window.removeEventListener(`test-${index}`, listener);
      });
    });

    const finalMemory = performance.memory ? performance.memory.usedJSHeapSize : 0;

    return {
      initialMemory,
      peakMemory,
      finalMemory,
      memoryIncrease: peakMemory - initialMemory,
      memoryLeakage: finalMemory - initialMemory
    };
  }

  // 生成测试报告
  generateReport(performanceResults, memoryResults) {
    return `
## 微前端通信方式性能测试报告

### 性能测试结果 (${this.testIterations} 次操作)

| 通信方式 | 绝对时间(ms) | 相对性能 | 吞吐量 |
|---------|-------------|---------|--------|
${Object.entries(performanceResults).map(([method, result]) => 
  `| ${method} | ${result.absoluteTime.toFixed(2)} | ${result.relativePerformance} | ${result.throughput} |`
).join('\n')}

### 内存使用测试

- 初始内存: ${(memoryResults.initialMemory / 1024 / 1024).toFixed(2)} MB
- 峰值内存: ${(memoryResults.peakMemory / 1024 / 1024).toFixed(2)} MB
- 最终内存: ${(memoryResults.finalMemory / 1024 / 1024).toFixed(2)} MB
- 内存增长: ${(memoryResults.memoryIncrease / 1024 / 1024).toFixed(2)} MB
- 内存泄漏: ${(memoryResults.memoryLeakage / 1024 / 1024).toFixed(2)} MB

### 推荐建议

${this.generateRecommendations(performanceResults, memoryResults)}
    `;
  }

  generateRecommendations(performanceResults, memoryResults) {
    const recommendations = [];
    
    // 性能推荐
    const fastestMethod = Object.entries(performanceResults).reduce((a, b) => 
      a[1].absoluteTime < b[1].absoluteTime ? a : b
    )[0];
    
    recommendations.push(`- 性能最优: ${fastestMethod}`);
    
    // 内存推荐
    if (memoryResults.memoryLeakage > 1024 * 1024) { // 1MB
      recommendations.push('- 注意内存泄漏,及时清理事件监听器');
    }
    
    if (memoryResults.memoryIncrease > 10 * 1024 * 1024) { // 10MB
      recommendations.push('- 考虑使用更轻量级的通信方案');
    }
    
    return recommendations.join('\n');
  }
}

// 运行性能测试
async function runCommunicationTests() {
  const testSuite = new CommunicationPerformanceTest();
  
  const performanceResults = await testSuite.runFullPerformanceTest();
  const memoryResults = await testSuite.testMemoryUsage();
  
  const report = testSuite.generateReport(performanceResults, memoryResults);
  console.log(report);
  
  return { performanceResults, memoryResults, report };
}

5.4 通信方案最佳实践

javascript 复制代码
// 通信方案最佳实践
class CommunicationBestPractices {
  static getRecommendation(scenario) {
    const recommendations = {
      'simple-events': {
        solution: 'Custom Events',
        reason: '简单直接,无额外依赖',
        implementation: 'window.dispatchEvent + addEventListener'
      },
      
      'complex-interaction': {
        solution: 'Event Bus',
        reason: '支持复杂的事件管理和取消监听',
        implementation: '自定义EventBus类'
      },
      
      'state-sharing': {
        solution: 'Global State Manager',
        reason: '状态持久化和自动同步',
        implementation: 'Proxy + Subscription模式'
      },
      
      'cross-origin': {
        solution: 'PostMessage',
        reason: '安全的跨域通信',
        implementation: 'iframe + postMessage API'
      },
      
      'real-time': {
        solution: 'WebSocket',
        reason: '实时双向通信',
        implementation: 'WebSocket + 消息路由'
      },
      
      'multi-tab': {
        solution: 'SharedWorker',
        reason: '多标签页状态同步',
        implementation: 'SharedWorker + MessagePort'
      }
    };

    return recommendations[scenario] || recommendations['simple-events'];
  }

  static createOptimalCommunicator(scenarios) {
    // 根据多个场景创建最优的通信器组合
    const communicators = [];
    
    scenarios.forEach(scenario => {
      const recommendation = this.getRecommendation(scenario);
      communicators.push(recommendation);
    });

    return new HybridCommunicator(communicators);
  }
}

// 混合通信器
class HybridCommunicator {
  constructor(communicators) {
    this.communicators = new Map();
    this.init(communicators);
  }

  init(communicators) {
    communicators.forEach((config, index) => {
      let communicator;
      
      switch (config.solution) {
        case 'Custom Events':
          communicator = new CustomEventCommunicator();
          break;
        case 'Event Bus':
          communicator = new EventBusCommunicator();
          break;
        case 'Global State Manager':
          communicator = new StateCommunicator();
          break;
        case 'PostMessage':
          communicator = new PostMessageCommunicator();
          break;
        case 'WebSocket':
          communicator = new WebSocketCommunicator();
          break;
        case 'SharedWorker':
          communicator = new SharedWorkerCommunicator();
          break;
      }
      
      this.communicators.set(config.solution, communicator);
    });
  }

  // 智能路由消息到最适合的通信器
  send(message, options = {}) {
    const { type, target, data, priority = 'normal' } = options;
    
    let communicator;
    
    // 根据消息特征选择通信器
    if (target && target.includes('iframe')) {
      communicator = this.communicators.get('PostMessage');
    } else if (type === 'state-change') {
      communicator = this.communicators.get('Global State Manager');
    } else if (priority === 'real-time') {
      communicator = this.communicators.get('WebSocket');
    } else {
      communicator = this.communicators.get('Event Bus') || 
                    this.communicators.get('Custom Events');
    }
    
    if (communicator && communicator.send) {
      return communicator.send(message, options);
    } else {
      console.warn('No suitable communicator found for message:', message);
    }
  }

  // 统一的监听接口
  on(event, handler, options = {}) {
    const communicators = options.communicators || Array.from(this.communicators.values());
    
    const unsubscribers = communicators.map(communicator => {
      if (communicator.on) {
        return communicator.on(event, handler, options);
      }
    }).filter(Boolean);

    return () => {
      unsubscribers.forEach(unsubscribe => unsubscribe());
    };
  }

  // 获取通信统计
  getStats() {
    const stats = {};
    
    this.communicators.forEach((communicator, name) => {
      if (communicator.getStats) {
        stats[name] = communicator.getStats();
      }
    });

    return stats;
  }
}

// 使用示例
const scenarios = ['simple-events', 'state-sharing', 'cross-origin'];
const communicator = CommunicationBestPractices.createOptimalCommunicator(scenarios);

// 发送不同类型的消息
communicator.send({ type: 'user-login', userId: 123 }, { 
  type: 'event', 
  priority: 'normal' 
});

communicator.send({ user: { id: 123, name: 'John' } }, { 
  type: 'state-change' 
});

communicator.send({ message: 'Hello iframe' }, { 
  target: 'iframe-app', 
  type: 'cross-origin' 
});

// 统一监听
communicator.on('user-status-change', (data) => {
  console.log('用户状态变化:', data);
});
相关推荐
王者鳜錸1 小时前
VUE+SPRINGBOOT从0-1打造前后端-前后台系统-邮箱重置密码
前端·vue.js·spring boot
独泪了无痕3 小时前
深入浅析Vue3中的生命周期钩子函数
前端·vue.js
小白白一枚1113 小时前
vue和react的框架原理
前端·vue.js·react.js
字节逆旅3 小时前
从一次爬坑看前端的出路
前端·后端·程序员
若梦plus4 小时前
Babel中微内核&插件化思想的应用
前端·babel
若梦plus4 小时前
微前端中微内核&插件化思想的应用
前端
若梦plus4 小时前
服务化架构中微内核&插件化思想的应用
前端
若梦plus4 小时前
Electron中微内核&插件化思想的应用
前端·electron
若梦plus4 小时前
Vue.js中微内核&插件化思想的应用
前端