Skip to content
On this page

qiankun 性能优化

性能优化概述

qiankun 微前端架构的性能优化涉及多个层面,包括微应用加载性能、内存管理、资源优化等方面。合理的优化策略可以显著提升用户体验和应用响应速度。

加载性能优化

1. 预加载策略

基础预加载

javascript
// 启用默认预加载
start({
  prefetch: true, // 预加载所有微应用
});

智能预加载

javascript
// 自定义预加载策略
start({
  prefetch: {
    // 关键应用立即预加载
    criticalAppList: [
      { 
        name: 'user-center', 
        entry: '//localhost:3001',
        // 自定义预加载逻辑
        prefetchMethod: async () => {
          // 可以根据用户角色、权限等条件决定是否预加载
          return isUserLoggedIn() && hasPermission('user-center');
        }
      }
    ],
    // 非关键应用空闲时预加载
    idleAppList: [
      { name: 'reporting', entry: '//localhost:3002' }
    ],
  }
});

条件预加载

javascript
// 基于用户行为的预加载
let userBehavior = {
  visitedPages: [],
  timeOnPage: {},
  navigationPattern: []
};

// 记录用户行为
function recordUserBehavior(page, time) {
  userBehavior.visitedPages.push(page);
  userBehavior.timeOnPage[page] = time || Date.now();
  
  // 限制记录数量
  if (userBehavior.visitedPages.length > 10) {
    userBehavior.visitedPages.shift();
  }
}

// 预测用户可能访问的微应用
function predictNextMicroApp() {
  const recentPages = userBehavior.visitedPages.slice(-3);
  
  // 简单的预测逻辑
  if (recentPages.includes('/order') && recentPages.includes('/product')) {
    return 'payment'; // 可能会访问支付页面
  }
  
  return null;
}

// 动态调整预加载
function dynamicPrefetch() {
  const predictedApp = predictNextMicroApp();
  if (predictedApp) {
    // 预加载预测的应用
    prefetchApp(predictedApp);
  }
}

2. 资源优化

代码分割

javascript
// 微应用代码分割配置
// webpack.config.js
module.exports = {
  optimization: {
    splitChunks: {
      chunks: 'all',
      cacheGroups: {
        // 分离公共依赖
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          chunks: 'all',
          priority: 10
        },
        // 分离微应用特定代码
        microApp: {
          test: /[\\/]src[\\/]/,
          name: 'micro-app',
          chunks: 'all',
          priority: 5
        }
      }
    }
  }
};

懒加载资源

javascript
// 微应用中的懒加载实现
export async function mount(props) {
  const { container } = props;
  
  // 立即加载关键资源
  await loadCriticalResources();
  
  // 延迟加载非关键资源
  setTimeout(async () => {
    await loadNonCriticalResources();
  }, 0);
  
  // 或使用 Intersection Observer 延迟加载
  const lazyLoadObserver = new IntersectionObserver((entries) => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        loadLazyComponent(entry.target);
        lazyLoadObserver.unobserve(entry.target);
      }
    });
  });
}

async function loadCriticalResources() {
  // 加载关键的 CSS 和 JS
  const criticalResources = [
    '/css/critical.css',
    '/js/vendor.js'
  ];
  
  await Promise.all(criticalResources.map(loadResource));
}

function loadResource(url) {
  return new Promise((resolve, reject) => {
    if (url.endsWith('.css')) {
      const link = document.createElement('link');
      link.rel = 'stylesheet';
      link.href = url;
      link.onload = resolve;
      link.onerror = reject;
      document.head.appendChild(link);
    } else if (url.endsWith('.js')) {
      const script = document.createElement('script');
      script.src = url;
      script.onload = resolve;
      script.onerror = reject;
      document.head.appendChild(script);
    }
  });
}

3. 缓存策略

应用实例缓存

javascript
// 应用实例缓存管理
class MicroAppCache {
  constructor(options = {}) {
    this.cache = new Map();
    this.maxCacheSize = options.maxCacheSize || 5;
    this.ttl = options.ttl || 5 * 60 * 1000; // 5分钟过期时间
  }
  
  set(name, instance) {
    // 检查缓存大小
    if (this.cache.size >= this.maxCacheSize) {
      // 移除最久未使用的实例
      const firstKey = this.cache.keys().next().value;
      this.delete(firstKey);
    }
    
    this.cache.set(name, {
      instance,
      timestamp: Date.now(),
      lastAccessed: Date.now()
    });
  }
  
  get(name) {
    const cached = this.cache.get(name);
    if (cached) {
      // 检查是否过期
      if (Date.now() - cached.timestamp > this.ttl) {
        this.delete(name);
        return null;
      }
      
      cached.lastAccessed = Date.now();
      return cached.instance;
    }
    return null;
  }
  
  delete(name) {
    const cached = this.cache.get(name);
    if (cached && cached.instance) {
      // 确保正确清理实例
      if (typeof cached.instance.unmount === 'function') {
        cached.instance.unmount();
      }
    }
    this.cache.delete(name);
  }
  
  clear() {
    for (const [name] of this.cache) {
      this.delete(name);
    }
  }
  
  // 定期清理过期缓存
  startCleanupTimer() {
    setInterval(() => {
      for (const [name, cached] of this.cache) {
        if (Date.now() - cached.timestamp > this.ttl) {
          this.delete(name);
        }
      }
    }, 60 * 1000); // 每分钟检查一次
  }
}

const appCache = new MicroAppCache({
  maxCacheSize: 3,
  ttl: 10 * 60 * 1000 // 10分钟过期
});

资源缓存

javascript
// 资源缓存管理
class ResourceCache {
  constructor() {
    this.cache = new Map();
    this.maxSize = 100; // 最大缓存项目数
  }
  
  async fetch(url, options = {}) {
    if (this.cache.has(url)) {
      const cached = this.cache.get(url);
      if (Date.now() - cached.timestamp < cached.ttl) {
        return cached.data;
      } else {
        this.cache.delete(url);
      }
    }
    
    const response = await fetch(url, options);
    const data = await response.clone().text();
    
    if (this.cache.size >= this.maxSize) {
      // 删除最久未使用的项目
      const firstKey = this.cache.keys().next().value;
      this.cache.delete(firstKey);
    }
    
    this.cache.set(url, {
      data,
      timestamp: Date.now(),
      ttl: options.ttl || 5 * 60 * 1000 // 默认5分钟
    });
    
    return data;
  }
}

内存管理优化

1. 正确的生命周期管理

完整的资源清理

javascript
// 微应用完整的生命周期实现
let app = null;
let eventListeners = new Set();
let timers = new Set();
let observers = new Set();
let intervals = new Set();

export async function mount(props) {
  const { container } = props;
  
  // 创建应用实例
  app = new Vue({
    router,
    store,
    render: h => h(App),
  }).$mount(container ? container.querySelector('#app') : '#app');
  
  // 添加事件监听器
  const handleResize = () => {
    // 处理窗口大小变化
  };
  window.addEventListener('resize', handleResize);
  eventListeners.add(() => window.removeEventListener('resize', handleResize));
  
  // 添加定时器
  const timer = setTimeout(() => {
    // 定时任务
  }, 5000);
  timers.add(timer);
  
  // 添加间隔定时器
  const interval = setInterval(() => {
    // 重复任务
  }, 1000);
  intervals.add(interval);
  
  // 添加观察器
  const resizeObserver = new ResizeObserver(entries => {
    // 观察元素大小变化
  });
  resizeObserver.observe(container);
  observers.add(() => resizeObserver.disconnect());
}

export async function unmount(props) {
  // 清理事件监听器
  eventListeners.forEach(cleanup => cleanup());
  eventListeners.clear();
  
  // 清理定时器
  timers.forEach(timer => clearTimeout(timer));
  timers.clear();
  
  // 清理间隔定时器
  intervals.forEach(interval => clearInterval(interval));
  intervals.clear();
  
  // 清理观察器
  observers.forEach(cleanup => cleanup());
  observers.clear();
  
  // 销毁应用实例
  if (app) {
    app.$destroy();
    app.$el.innerHTML = '';
    app = null;
  }
  
  // 清理全局变量
  if (window.__MICRO_APP__) {
    delete window.__MICRO_APP__;
  }
}

2. 内存泄漏防护

内存监控

javascript
// 内存使用监控
class MemoryMonitor {
  constructor(options = {}) {
    this.checkInterval = options.checkInterval || 30000; // 30秒检查一次
    this.warnThreshold = options.warnThreshold || 100 * 1024 * 1024; // 100MB
    this.startMonitoring();
  }
  
  startMonitoring() {
    if (this.intervalId) {
      clearInterval(this.intervalId);
    }
    
    this.intervalId = setInterval(() => {
      this.checkMemoryUsage();
    }, this.checkInterval);
  }
  
  checkMemoryUsage() {
    if (performance.memory) {
      const memory = performance.memory;
      const usage = memory.usedJSHeapSize;
      
      if (usage > this.warnThreshold) {
        console.warn('Memory usage high:', {
          used: (usage / 1024 / 1024).toFixed(2) + 'MB',
          total: (memory.totalJSHeapSize / 1024 / 1024).toFixed(2) + 'MB',
          limit: (memory.jsHeapSizeLimit / 1024 / 1024).toFixed(2) + 'MB'
        });
        
        // 可以触发内存清理
        this.triggerCleanup();
      }
    }
  }
  
  triggerCleanup() {
    // 强制垃圾回收(仅在开发环境)
    if (process.env.NODE_ENV === 'development' && window.gc) {
      window.gc();
    }
  }
  
  stopMonitoring() {
    if (this.intervalId) {
      clearInterval(this.intervalId);
      this.intervalId = null;
    }
  }
}

const memoryMonitor = new MemoryMonitor({
  checkInterval: 60000, // 1分钟检查一次
  warnThreshold: 150 * 1024 * 1024 // 150MB 警告阈值
});

网络性能优化

1. 请求优化

请求缓存和去重

javascript
// 请求缓存管理
class RequestCache {
  constructor() {
    this.cache = new Map();
    this.pending = new Map(); // 正在进行的请求
  }
  
  async request(url, options = {}) {
    // 检查是否有相同的请求正在进行
    if (this.pending.has(url)) {
      return this.pending.get(url);
    }
    
    // 检查缓存
    if (this.cache.has(url) && !this.isExpired(this.cache.get(url))) {
      return this.cache.get(url).data;
    }
    
    // 发起新请求
    const promise = fetch(url, options).then(response => response.json())
      .then(data => {
        // 缓存结果
        this.cache.set(url, {
          data,
          timestamp: Date.now(),
          ttl: options.ttl || 5 * 60 * 1000 // 5分钟
        });
        return data;
      })
      .finally(() => {
        this.pending.delete(url);
      });
    
    this.pending.set(url, promise);
    return promise;
  }
  
  isExpired(cached) {
    return Date.now() - cached.timestamp > cached.ttl;
  }
}

const requestCache = new RequestCache();

2. 资源预加载

智能预加载

javascript
// 智能资源预加载
class SmartPreloader {
  constructor() {
    this.preloaded = new Set();
    this.loading = new Map();
  }
  
  async preloadResource(url, priority = 'normal') {
    if (this.preloaded.has(url)) {
      return Promise.resolve();
    }
    
    if (this.loading.has(url)) {
      return this.loading.get(url);
    }
    
    const loadPromise = this.loadResource(url);
    this.loading.set(url, loadPromise);
    
    return loadPromise.finally(() => {
      this.loading.delete(url);
    });
  }
  
  async loadResource(url) {
    if (url.endsWith('.js')) {
      return this.preloadScript(url);
    } else if (url.endsWith('.css')) {
      return this.preloadStylesheet(url);
    } else if (/\.(png|jpg|jpeg|gif|svg|webp)$/.test(url)) {
      return this.preloadImage(url);
    }
  }
  
  preloadScript(url) {
    return new Promise((resolve, reject) => {
      const link = document.createElement('link');
      link.rel = 'preload';
      link.as = 'script';
      link.href = url;
      link.onload = () => {
        this.preloaded.add(url);
        resolve();
      };
      link.onerror = reject;
      document.head.appendChild(link);
    });
  }
  
  preloadStylesheet(url) {
    return new Promise((resolve, reject) => {
      const link = document.createElement('link');
      link.rel = 'preload';
      link.as = 'style';
      link.href = url;
      link.onload = () => {
        this.preloaded.add(url);
        resolve();
      };
      link.onerror = reject;
      document.head.appendChild(link);
    });
  }
  
  preloadImage(url) {
    return new Promise((resolve, reject) => {
      const img = new Image();
      img.onload = () => {
        this.preloaded.add(url);
        resolve();
      };
      img.onerror = reject;
      img.src = url;
    });
  }
}

const smartPreloader = new SmartPreloader();

渲染性能优化

1. 虚拟滚动

长列表优化

javascript
// 虚拟滚动实现(概念示例)
class VirtualList {
  constructor(container, options = {}) {
    this.container = container;
    this.itemHeight = options.itemHeight || 50;
    this.visibleCount = options.visibleCount || 10;
    this.data = [];
    this.renderedItems = new Map();
  }
  
  setData(data) {
    this.data = data;
    this.updateVisibleItems();
  }
  
  updateVisibleItems() {
    const scrollTop = this.container.scrollTop;
    const start = Math.floor(scrollTop / this.itemHeight);
    const end = Math.min(start + this.visibleCount, this.data.length);
    
    // 清理不在视口的项目
    for (const [index, element] of this.renderedItems) {
      if (index < start || index >= end) {
        this.container.removeChild(element);
        this.renderedItems.delete(index);
      }
    }
    
    // 添加新的可见项目
    for (let i = start; i < end; i++) {
      if (!this.renderedItems.has(i)) {
        const itemElement = this.createItemElement(this.data[i], i);
        itemElement.style.transform = `translateY(${i * this.itemHeight}px)`;
        this.container.appendChild(itemElement);
        this.renderedItems.set(i, itemElement);
      }
    }
  }
  
  createItemElement(item, index) {
    const element = document.createElement('div');
    element.className = 'virtual-list-item';
    element.innerHTML = item.content;
    return element;
  }
}

2. 组件懒加载

路由级懒加载

javascript
// 微应用中的路由懒加载
import { createRouter, createWebHistory } from 'vue-router';

function createRouter() {
  return createRouter({
    history: createWebHistory(),
    routes: [
      { 
        path: '/', 
        component: () => import('./views/Home.vue') // 懒加载
      },
      { 
        path: '/profile', 
        component: () => import('./views/Profile.vue') // 懒加载
      },
      {
        path: '/settings',
        component: () => import(
          /* webpackChunkName: "settings" */ 
          './views/Settings.vue'
        )
      }
    ]
  });
}

主应用优化

1. 应用切换优化

平滑切换

javascript
// 主应用中的平滑切换实现
class AppSwitcher {
  constructor() {
    this.currentApp = null;
    this.transitionDuration = 300; // 300ms 切换动画
  }
  
  async switchTo(appName) {
    const container = document.getElementById('subapp-container');
    
    // 添加切换动画
    container.style.transition = `opacity ${this.transitionDuration}ms ease`;
    container.style.opacity = '0';
    
    // 延迟切换以确保动画效果
    setTimeout(async () => {
      if (this.currentApp) {
        // 隐藏当前应用
        this.hideCurrentApp();
      }
      
      // 显示新应用
      await this.showApp(appName);
      
      container.style.opacity = '1';
    }, this.transitionDuration / 2);
  }
  
  hideCurrentApp() {
    if (this.currentApp) {
      // 触发当前应用的隐藏逻辑
      this.currentApp.style.display = 'none';
    }
  }
  
  async showApp(appName) {
    // 显示新应用
    const appContainer = document.getElementById(appName);
    if (appContainer) {
      appContainer.style.display = 'block';
    }
  }
}

const appSwitcher = new AppSwitcher();

2. 资源管理

资源预加载管理

javascript
// 主应用资源预加载
class MainAppPreloader {
  constructor() {
    this.preloadedApps = new Set();
    this.preloadQueue = [];
    this.isPreloading = false;
  }
  
  async preloadApps(appNames) {
    if (this.isPreloading) {
      // 如果正在预加载,添加到队列
      this.preloadQueue.push(...appNames);
      return;
    }
    
    this.isPreloading = true;
    
    try {
      for (const appName of appNames) {
        if (!this.preloadedApps.has(appName)) {
          await this.preloadApp(appName);
          this.preloadedApps.add(appName);
        }
      }
    } finally {
      this.isPreloading = false;
      
      // 处理队列中的预加载请求
      if (this.preloadQueue.length > 0) {
        const nextBatch = this.preloadQueue.splice(0, 3); // 每次处理3个
        this.preloadApps(nextBatch);
      }
    }
  }
  
  async preloadApp(appName) {
    // 模拟预加载应用
    return new Promise(resolve => {
      setTimeout(() => {
        console.log(`Preloaded app: ${appName}`);
        resolve();
      }, 100); // 模拟网络请求时间
    });
  }
}

const mainAppPreloader = new MainAppPreloader();

监控和分析

1. 性能监控

性能指标收集

javascript
// 性能监控工具
class PerformanceMonitor {
  constructor() {
    this.metrics = {
      loadTimes: {},
      memoryUsage: [],
      renderTimes: {},
      errorCounts: {}
    };
  }
  
  startAppLoad(appName) {
    this.metrics.loadTimes[appName] = {
      startTime: performance.now()
    };
  }
  
  endAppLoad(appName) {
    if (this.metrics.loadTimes[appName]) {
      this.metrics.loadTimes[appName].endTime = performance.now();
      this.metrics.loadTimes[appName].duration = 
        this.metrics.loadTimes[appName].endTime - this.metrics.loadTimes[appName].startTime;
      
      console.log(`App ${appName} loaded in ${this.metrics.loadTimes[appName].duration}ms`);
    }
  }
  
  recordRenderTime(appName, time) {
    if (!this.metrics.renderTimes[appName]) {
      this.metrics.renderTimes[appName] = [];
    }
    this.metrics.renderTimes[appName].push(time);
    
    // 计算平均渲染时间
    const avg = this.metrics.renderTimes[appName].reduce((a, b) => a + b) / 
                this.metrics.renderTimes[appName].length;
    console.log(`Avg render time for ${appName}: ${avg}ms`);
  }
  
  recordError(appName, errorType) {
    if (!this.metrics.errorCounts[appName]) {
      this.metrics.errorCounts[appName] = {};
    }
    
    if (!this.metrics.errorCounts[appName][errorType]) {
      this.metrics.errorCounts[appName][errorType] = 0;
    }
    
    this.metrics.errorCounts[appName][errorType]++;
  }
  
  getMetrics() {
    return this.metrics;
  }
}

const perfMonitor = new PerformanceMonitor();

2. 性能分析

Web Vitals 集成

javascript
// Web Vitals 监控
import { getCLS, getFID, getFCP, getLCP, getTTFB } from 'web-vitals';

function sendToAnalytics(metric) {
  // 发送性能指标到分析服务
  console.log('Performance metric:', metric);
}

// 监控核心 Web Vitals
getCLS(sendToAnalytics);
getFID(sendToAnalytics);
getFCP(sendToAnalytics);
getLCP(sendToAnalytics);
getTTFB(sendToAnalytics);

// 自定义 qiankun 相关指标
function measureMicroAppPerformance() {
  // 监控微应用加载时间
  const observer = new PerformanceObserver((list) => {
    for (const entry of list.getEntries()) {
      if (entry.name.includes('micro-app')) {
        console.log('Micro app performance:', entry);
      }
    }
  });
  
  observer.observe({ entryTypes: ['navigation', 'resource'] });
}

measureMicroAppPerformance();

通过以上性能优化策略,可以显著提升 qiankun 微前端应用的性能表现,提供更好的用户体验。