Skip to content
On this page

qiankun 工具与资源

官方工具

1. qiankun 核心库

安装和基本使用

bash
# 安装 qiankun
npm install qiankun
# 或
yarn add qiankun
# 或
pnpm add qiankun

TypeScript 类型定义

typescript
// qiankun 类型定义示例
import { 
  registerMicroApps, 
  start, 
  loadMicroApp, 
  initGlobalState,
  MicroApp
} from 'qiankun';

interface AppConfiguration {
  name: string;
  entry: string;
  container: string;
  activeRule: string | ((location: Location) => boolean);
  props?: Record<string, any>;
}

interface GlobalState {
  user?: {
    id: number;
    name: string;
  };
  theme?: string;
  language?: string;
}

2. 官方 CLI 工具

@qiankunjs/vite-plugin

bash
# 安装 Vite 插件
npm install @qiankunjs/vite-plugin --save-dev
javascript
// vite.config.js
import { defineConfig } from 'vite';
import qiankun from '@qiankunjs/vite-plugin';

export default defineConfig({
  plugins: [
    qiankun({
      name: 'micro-app',
      entry: '/entry',
      // 其他配置
    })
  ]
});

@qiankunjs/vue-cli-plugin

bash
# 安装 Vue CLI 插件
vue add @qiankunjs/vue-cli-plugin

开发工具

1. 调试工具

qiankun-devtools 浏览器扩展

javascript
// 启用开发者工具
if (process.env.NODE_ENV === 'development') {
  // qiankun 内置开发工具
  window.__QIANKUN_DEVELOPMENT__ = true;
  
  // 自定义调试工具
  import('./devtools').then(module => {
    module.setupDevTools();
  });
}

自定义调试面板

javascript
// devtools.js - 自定义调试工具
export class QiankunDevTools {
  constructor() {
    this.panel = null;
    this.isOpen = false;
    this.apps = new Map();
  }

  init() {
    this.createPanel();
    this.setupEventListeners();
    this.startMonitoring();
  }

  createPanel() {
    this.panel = document.createElement('div');
    this.panel.id = 'qiankun-devtools-panel';
    this.panel.innerHTML = `
      <div class="qiankun-devtools">
        <div class="header">
          <h3>qiankun DevTools</h3>
          <button onclick="window.qiankunDevTools.toggle()">×</button>
        </div>
        <div class="content">
          <div class="apps-section">
            <h4>Registered Apps</h4>
            <div id="apps-list"></div>
          </div>
          <div class="state-section">
            <h4>Global State</h4>
            <pre id="global-state"></pre>
          </div>
          <div class="actions">
            <button onclick="window.qiankunDevTools.refresh()">Refresh</button>
            <button onclick="window.qiankunDevTools.clearLogs()">Clear Logs</button>
          </div>
        </div>
      </div>
    `;
    
    document.body.appendChild(this.panel);
    this.updateAppsList();
  }

  updateAppsList() {
    const appsList = document.getElementById('apps-list');
    const apps = this.getRegisteredApps();
    
    appsList.innerHTML = apps.map(app => `
      <div class="app-item">
        <span class="app-name">${app.name}</span>
        <span class="app-status">${app.status}</span>
      </div>
    `).join('');
  }

  getRegisteredApps() {
    // 获取已注册的微应用信息
    return Array.from(this.apps.entries()).map(([name, app]) => ({
      name,
      status: app.getStatus ? app.getStatus() : 'unknown',
      entry: app.entry || 'unknown'
    }));
  }

  setupEventListeners() {
    // 监听键盘快捷键
    document.addEventListener('keydown', (e) => {
      if (e.ctrlKey && e.key === 'q' && e.shiftKey) {
        e.preventDefault();
        this.toggle();
      }
    });
  }

  startMonitoring() {
    // 开始监控微应用状态
    setInterval(() => {
      this.updateAppsList();
      this.updateGlobalState();
    }, 1000);
  }

  updateGlobalState() {
    if (window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__) {
      const stateElement = document.getElementById('global-state');
      stateElement.textContent = JSON.stringify(
        this.getGlobalState(), 
        null, 2
      );
    }
  }

  getGlobalState() {
    // 获取全局状态
    if (window.__QIANKUN_GLOBAL_STATE__) {
      return window.__QIANKUN_GLOBAL_STATE__;
    }
    return {};
  }

  toggle() {
    this.panel.style.display = this.isOpen ? 'none' : 'block';
    this.isOpen = !this.isOpen;
  }

  refresh() {
    location.reload();
  }

  clearLogs() {
    console.clear();
  }
}

// 全局访问
window.qiankunDevTools = new QiankunDevTools();
window.qiankunDevTools.init();

2. 构建工具集成

Webpack 配置工具

javascript
// webpack-qiankun-config.js
const path = require('path');

class QiankunWebpackPlugin {
  constructor(options = {}) {
    this.options = {
      name: options.name || 'micro-app',
      entry: options.entry || '/entry',
      ...options
    };
  }

  apply(compiler) {
    // 配置输出
    compiler.options.output = {
      ...compiler.options.output,
      library: this.options.name,
      libraryTarget: 'umd',
      jsonpFunction: `webpackJsonp_${this.options.name}`,
      globalObject: 'window',
    };

    // 配置开发服务器
    if (compiler.options.mode === 'development') {
      compiler.options.devServer = {
        ...compiler.options.devServer,
        headers: {
          'Access-Control-Allow-Origin': '*',
        },
        hot: true,
      };
    }

    // 添加插件
    compiler.hooks.afterEnvironment.tap('QiankunPlugin', () => {
      // 自定义配置逻辑
    });
  }
}

module.exports = QiankunWebpackPlugin;

Vite 配置工具

javascript
// vite-qiankun-plugin.js
import { createHtmlPlugin } from 'vite-plugin-html';

export function qiankunPlugin(options = {}) {
  const { name = 'micro-app', enableBase = false } = options;

  return {
    name: 'qiankun',
    config(config) {
      config.build = {
        ...config.build,
        rollupOptions: {
          ...config.build?.rollupOptions,
          output: {
            ...config.build?.rollupOptions?.output,
            format: 'umd',
            entryFileNames: '[name].js',
            chunkFileNames: '[name].js',
            assetFileNames: '[name].[ext]',
          }
        }
      };

      config.define = {
        ...config.define,
        __QIANKUN_APP_NAME__: JSON.stringify(name),
        __QIANKUN_ENABLE_BASE__: enableBase,
      };
    },

    transformIndexHtml(html) {
      if (enableBase) {
        return html.replace(
          '<head>',
          '<head><base href="/" />'
        );
      }
      return html;
    }
  };
}

社区工具

1. 微应用生成器

@qiankun/cli

bash
# 安装 qiankun CLI
npm install -g @qiankun/cli

# 创建新的微应用
qiankun create my-micro-app
# 或选择模板
qiankun create my-app --template react
qiankun create my-app --template vue

微应用模板

javascript
// qiankun-app-template.js
module.exports = {
  templates: {
    react: {
      files: [
        'src/main.jsx',
        'src/App.jsx',
        'src/index.css',
        'public/index.html'
      ],
      dependencies: ['react', 'react-dom', 'react-router-dom'],
      devDependencies: ['@vitejs/plugin-react']
    },
    vue: {
      files: [
        'src/main.js',
        'src/App.vue',
        'src/router/index.js',
        'public/index.html'
      ],
      dependencies: ['vue', 'vue-router'],
      devDependencies: ['@vitejs/plugin-vue']
    }
  }
};

2. 状态管理工具

@qiankunjs/use-global-state

bash
npm install @qiankunjs/use-global-state
javascript
// 使用全局状态 hook
import { useGlobalState } from '@qiankunjs/use-global-state';

function UserProfile() {
  const [user, setUser] = useGlobalState('user');
  const [theme, setTheme] = useGlobalState('theme');

  return (
    <div>
      <h1>{user?.name}</h1>
      <button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
        Switch to {theme === 'light' ? 'dark' : 'light'} mode
      </button>
    </div>
  );
}

3. 路由管理工具

@qiankunjs/router

bash
npm install @qiankunjs/router
javascript
// 微应用路由配置
import { createQiankunRouter } from '@qiankunjs/router';
import { createRouter, createWebHistory } from 'vue-router';

export function createMicroRouter(basePath = '') {
  const router = createRouter({
    history: createWebHistory(basePath),
    routes: [
      { path: '/', component: () => import('./views/Home.vue') },
      { path: '/profile', component: () => import('./views/Profile.vue') },
    ]
  });

  return createQiankunRouter(router);
}

测试工具

1. 测试工具库

@qiankunjs/test-utils

bash
npm install --save-dev @qiankunjs/test-utils
javascript
// 测试工具使用示例
import { 
  createMockMicroApp, 
  simulateAppLifecycle, 
  testCommunication 
} from '@qiankunjs/test-utils';

describe('Micro App Tests', () => {
  test('should handle lifecycle correctly', async () => {
    const mockApp = createMockMicroApp({
      name: 'test-app',
      entry: '//localhost:3001'
    });

    // 模拟应用生命周期
    await simulateAppLifecycle(mockApp, {
      bootstrap: true,
      mount: true,
      unmount: true
    });

    expect(mockApp.getStatus()).toBe('NOT_MOUNTED');
  });

  test('should communicate with main app', async () => {
    const communicationResult = await testCommunication({
      mainApp: createMockMainApp(),
      microApp: createMockMicroApp()
    });

    expect(communicationResult.success).toBe(true);
    expect(communicationResult.data).toBeDefined();
  });
});

2. E2E 测试工具

Cypress qiankun 插件

javascript
// cypress/support/commands.js
Cypress.Commands.add('loadMicroApp', (appName, options = {}) => {
  cy.window().then(win => {
    return win.loadMicroApp({
      name: appName,
      entry: options.entry || `//localhost:3001`,
      container: options.container || '#subapp-container'
    });
  });
});

Cypress.Commands.add('switchMicroApp', (appName) => {
  cy.visit(`/${appName}`);
  cy.get(`#subapp-container`).should('exist');
});

监控和分析工具

1. 性能监控

qiankun-performance-monitor

javascript
// 性能监控工具
class QiankunPerformanceMonitor {
  constructor() {
    this.metrics = {
      appLoadTimes: new Map(),
      resourceLoadTimes: new Map(),
      memoryUsage: [],
      renderTimes: new Map()
    };
  }

  startAppLoad(appName) {
    this.metrics.appLoadTimes.set(appName, {
      startTime: performance.now(),
      startMemory: this.getMemoryUsage()
    });
  }

  endAppLoad(appName) {
    const startData = this.metrics.appLoadTimes.get(appName);
    if (startData) {
      const endTime = performance.now();
      const endMemory = this.getMemoryUsage();
      
      const loadTime = endTime - startData.startTime;
      const memoryDelta = endMemory - startData.startMemory;
      
      return {
        loadTime,
        memoryDelta,
        timestamp: new Date().toISOString()
      };
    }
  }

  getMemoryUsage() {
    return performance.memory ? performance.memory.usedJSHeapSize : 0;
  }

  generateReport() {
    const report = {
      apps: {},
      summary: {
        totalApps: this.metrics.appLoadTimes.size,
        averageLoadTime: 0,
        totalMemoryDelta: 0
      }
    };

    let totalLoadTime = 0;
    let totalMemoryDelta = 0;

    for (const [appName, data] of this.metrics.appLoadTimes) {
      const result = this.endAppLoad(appName);
      if (result) {
        report.apps[appName] = result;
        totalLoadTime += result.loadTime;
        totalMemoryDelta += result.memoryDelta;
      }
    }

    report.summary.averageLoadTime = totalLoadTime / this.metrics.appLoadTimes.size;
    report.summary.totalMemoryDelta = totalMemoryDelta;

    return report;
  }
}

// 全局性能监控实例
window.qiankunPerfMonitor = new QiankunPerformanceMonitor();

2. 错误监控

错误收集工具

javascript
// 错误监控工具
class QiankunErrorMonitor {
  constructor(options = {}) {
    this.options = {
      reportUrl: options.reportUrl || '/api/errors',
      sampleRate: options.sampleRate || 1.0, // 采样率
      maxErrors: options.maxErrors || 100, // 最大错误数量
      ...options
    };
    
    this.errors = [];
    this.init();
  }

  init() {
    // 监听 JavaScript 错误
    window.addEventListener('error', (event) => {
      this.handleError({
        type: 'javascript',
        message: event.error.message,
        stack: event.error.stack,
        filename: event.filename,
        lineno: event.lineno,
        colno: event.colno,
        microAppName: this.getCurrentMicroAppName()
      });
    });

    // 监听未捕获的 Promise 错误
    window.addEventListener('unhandledrejection', (event) => {
      this.handleError({
        type: 'promise',
        message: event.reason.message || event.reason,
        stack: event.reason.stack,
        microAppName: this.getCurrentMicroAppName()
      });
    });

    // 监听 qiankun 特定错误
    if (window.__QIANKUN__) {
      // qiankun 错误处理
    }
  }

  handleError(error) {
    // 采样控制
    if (Math.random() > this.options.sampleRate) {
      return;
    }

    // 添加时间戳和上下文
    error.timestamp = new Date().toISOString();
    error.context = {
      url: window.location.href,
      userAgent: navigator.userAgent,
      microApp: error.microAppName
    };

    this.errors.push(error);

    // 限制错误数量
    if (this.errors.length > this.options.maxErrors) {
      this.errors = this.errors.slice(-this.options.maxErrors);
    }

    // 上报错误
    this.reportError(error);

    // 控制台输出
    if (process.env.NODE_ENV === 'development') {
      console.error('qiankun error:', error);
    }
  }

  async reportError(error) {
    try {
      await fetch(this.options.reportUrl, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          error,
          type: 'qiankun-error',
          timestamp: new Date().toISOString()
        })
      });
    } catch (reportError) {
      console.error('Failed to report error:', reportError);
    }
  }

  getCurrentMicroAppName() {
    // 根据当前路由或全局变量获取当前微应用名称
    const path = window.location.pathname;
    const appRoutes = {
      '/user': 'user-center',
      '/product': 'product-center',
      '/order': 'order-center'
    };

    for (const [route, appName] of Object.entries(appRoutes)) {
      if (path.startsWith(route)) {
        return appName;
      }
    }

    return 'unknown';
  }

  getErrors() {
    return [...this.errors];
  }

  clearErrors() {
    this.errors = [];
  }
}

// 初始化错误监控
window.qiankunErrorMonitor = new QiankunErrorMonitor({
  reportUrl: '/api/qiankun-errors',
  sampleRate: 0.8
});

部署和运维工具

1. 部署工具

Docker 部署模板

text
# Dockerfile for micro app
FROM node:16-alpine as builder

WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

FROM node:16-alpine
WORKDIR /app

# 复制依赖
COPY --from=builder /app/node_modules ./node_modules

# 复制应用代码
COPY . .

# 构建应用
RUN npm run build

# 暴露端口
EXPOSE 3000

# 启动应用
CMD ["npm", "start"]

Kubernetes 部署配置

yaml
# k8s-micro-app.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: micro-app
  labels:
    app: micro-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: micro-app
  template:
    metadata:
      labels:
        app: micro-app
    spec:
      containers:
      - name: micro-app
        image: micro-app:latest
        ports:
        - containerPort: 3000
        env:
        - name: PORT
          value: "3000"
        - name: NODE_ENV
          value: "production"
        resources:
          requests:
            memory: "128Mi"
            cpu: "100m"
          limits:
            memory: "256Mi"
            cpu: "200m"
---
apiVersion: v1
kind: Service
metadata:
  name: micro-app-service
spec:
  selector:
    app: micro-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 3000
  type: LoadBalancer

2. 监控面板

Grafana 监控配置

json
{
  "dashboard": {
    "id": null,
    "title": "qiankun Micro Frontends",
    "panels": [
      {
        "id": 1,
        "title": "App Load Times",
        "type": "graph",
        "targets": [
          {
            "expr": "qiankun_app_load_time",
            "legendFormat": "{{app}}"
          }
        ]
      },
      {
        "id": 2,
        "title": "Error Rates",
        "type": "graph",
        "targets": [
          {
            "expr": "rate(qiankun_errors_total[5m])",
            "legendFormat": "{{app}}"
          }
        ]
      }
    ]
  }
}

学习资源

1. 官方文档和教程

2. 社区资源

博客和文章

  • qiankun 最佳实践指南
  • 微前端架构设计模式
  • qiankun 性能优化技巧
  • 微应用通信模式详解

视频教程

  • qiankun 入门视频
  • 微前端架构实战
  • qiankun 高级特性

在线课程

  • 微前端架构完整课程
  • qiankun 深度解析
  • 微应用开发实战

3. 示例项目

完整示例

bash
# 克隆示例项目
git clone https://github.com/umijs/qiankun.git
cd qiankun/examples

# 主应用示例
cd main
npm install && npm start

# React 微应用示例
cd ../react16
npm install && npm start

# Vue 微应用示例
cd ../vue
npm install && npm start

企业级示例

bash
# 复杂企业级微前端示例
git clone https://github.com/qiankun-example/enterprise-micro-frontend.git

生态工具

1. 相关库和框架

微服务网关

  • API 网关集成
  • 认证和授权
  • 流量控制

状态管理

  • Redux Toolkit
  • Zustand
  • Pinia
  • Recoil

路由管理

  • React Router
  • Vue Router
  • Angular Router
  • Nuxt Router

2. 开发工具链

代码质量工具

json
{
  "eslintConfig": {
    "extends": [
      "@qiankunjs",
      "plugin:qiankun/recommended"
    ],
    "rules": {
      "qiankun/lifecycle-usage": "error",
      "qiankun/props-usage": "warn"
    }
  },
  "prettier": {
    "semi": true,
    "trailingComma": "es5",
    "singleQuote": true,
    "printWidth": 80
  }
}

Git Hooks

javascript
// .husky/pre-commit
#!/usr/bin/env sh
. "$(dirname "$0")/_/husky.sh"

npm run lint-staged
npm run test:unit

通过这些工具和资源,可以更好地开发、测试和维护基于 qiankun 的微前端应用。