Appearance
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 的微前端应用。