Appearance
qiankun 最佳实践
项目架构设计
1. 合理划分微应用
职责分离原则
- 按业务领域划分微应用
- 每个微应用应具有明确的业务边界
- 避免微应用间的循环依赖
javascript
// 示例:合理的微应用划分
const microApps = [
{
name: 'user-center', // 用户中心
entry: '//localhost:3001',
container: '#user-center-container',
activeRule: '/user',
},
{
name: 'order-management', // 订单管理
entry: '//localhost:3002',
container: '#order-container',
activeRule: '/order',
},
{
name: 'product-catalog', // 产品目录
entry: '//localhost:3003',
container: '#product-container',
activeRule: '/product',
}
];
技术栈选择
- 根据团队技术栈选择微应用实现
- 保持技术栈的一致性以降低维护成本
- 为新技术试点预留空间
2. 主应用设计
通用布局组件
javascript
// 主应用布局组件
function MainLayout() {
return (
<div className="main-layout">
<Header />
<Navigation />
<div id="subapp-container" className="subapp-container">
{/* 微应用将在此处渲染 */}
<div id="subapp-viewport" />
</div>
<Footer />
</div>
);
}
全局状态管理
javascript
// 主应用全局状态初始化
import { initGlobalState } from 'qiankun';
const initialState = {
user: null,
theme: 'light',
language: 'zh-CN',
notifications: [],
};
const { onGlobalStateChange, setGlobalState } = initGlobalState(initialState);
// 提供全局状态管理服务
export { onGlobalStateChange, setGlobalState };
微应用开发规范
1. 生命周期实现
标准生命周期实现
javascript
// 微应用标准入口
let app = null;
export async function bootstrap(props) {
console.log('微应用启动', props);
}
export async function mount(props) {
const { container, history, store, ...restProps } = props;
// 初始化应用
app = new Vue({
router: createRouter(history), // 传入 history 对象
store,
render: h => h(App),
});
// 挂载到指定容器
app.$mount(container ? container.querySelector('#app') : '#app');
console.log('微应用挂载完成');
}
export async function unmount(props) {
if (app) {
app.$destroy();
app.$el.innerHTML = '';
app = null;
}
console.log('微应用卸载完成');
}
错误处理
javascript
export async function mount(props) {
try {
// 应用初始化逻辑
app = new Vue({
router,
store,
render: h => h(App),
});
app.$mount(props.container ? props.container.querySelector('#app') : '#app');
} catch (error) {
console.error('微应用挂载失败:', error);
// 通知主应用错误状态
if (props.onError) {
props.onError(error);
}
// 提供降级方案
const container = props.container || document.getElementById('app');
container.innerHTML = '<div class="error-fallback">微应用加载失败</div>';
}
}
2. 路由管理
微应用路由配置
javascript
// 微应用路由配置
import { createRouter, createWebHistory } from 'vue-router';
function createRouter(history) {
return createRouter({
// 使用主应用传递的 history 或创建自己的
history: history || createWebHistory('/micro-app/'),
routes: [
{ path: '/', component: Home },
{ path: '/profile', component: Profile },
{ path: '/settings', component: Settings }
]
});
}
主应用路由协调
javascript
// 主应用路由配置
const mainRoutes = [
{ path: '/', component: Home },
{ path: '/micro-app', component: () => import('./MicroAppContainer') },
{ path: '/about', component: About }
];
通信机制设计
1. 数据传递
通过 props 传递数据
javascript
// 主应用注册微应用时传递数据
registerMicroApps([
{
name: 'user-profile',
entry: '//localhost:3001',
container: '#container',
activeRule: '/user',
props: {
// 用户信息
userInfo: getUserInfo(),
// 主题设置
theme: getTheme(),
// 回调函数
onUserUpdate: (userData) => {
// 处理用户信息更新
updateUserInMainApp(userData);
}
}
}
]);
通过全局状态通信
javascript
// 主应用状态管理
const { setGlobalState, onGlobalStateChange } = initGlobalState({
user: { id: 1, name: 'John' },
permissions: ['read', 'write'],
});
// 微应用中使用全局状态
export async function mount(props) {
const { onGlobalStateChange, setGlobalState } = props;
// 监听全局状态变化
onGlobalStateChange((state, prev) => {
if (state.user !== prev.user) {
// 用户信息变化,更新微应用状态
updateUserInterface(state.user);
}
}, true);
// 修改全局状态
const updateUserInfo = (newInfo) => {
setGlobalState({
user: { ...getGlobalState().user, ...newInfo }
});
};
// 将更新函数传递给应用
props.updateUserInfo = updateUserInfo;
}
2. 事件通信
自定义事件系统
javascript
// 微应用内部事件管理
class MicroAppEventEmitter {
constructor(props) {
this.props = props;
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));
}
// 同时通知主应用
if (this.props.onMicroEvent) {
this.props.onMicroEvent({ event, data });
}
}
off(event, callback) {
if (this.events[event]) {
const index = this.events[event].indexOf(callback);
if (index > -1) {
this.events[event].splice(index, 1);
}
}
}
}
性能优化策略
1. 预加载优化
智能预加载
javascript
// 基于用户行为的预加载
let userBehaviorHistory = [];
// 记录用户行为
function recordUserBehavior(path) {
userBehaviorHistory.push({
path,
timestamp: Date.now()
});
// 清理历史记录
userBehaviorHistory = userBehaviorHistory.slice(-10);
}
// 预测可能访问的应用
function predictNextApp() {
// 简单的预测算法
if (userBehaviorHistory.length >= 2) {
const lastPath = userBehaviorHistory[userBehaviorHistory.length - 1].path;
const secondLastPath = userBehaviorHistory[userBehaviorHistory.length - 2].path;
// 根据访问模式预测
if (lastPath === '/order' && secondLastPath === '/product') {
return 'payment'; // 可能会访问支付页面
}
}
return null;
}
// 动态调整预加载策略
function adjustPrefetchStrategy() {
const predictedApp = predictNextApp();
if (predictedApp) {
// 预加载预测的应用
preloadApp(predictedApp);
}
}
资源优化
javascript
// 微应用资源优化配置
export async function bootstrap() {
// 预加载关键资源
preloadCriticalAssets();
// 懒加载非关键资源
setTimeout(() => {
import('./non-critical-module').then(module => {
// 使用非关键模块
});
}, 0);
}
function preloadCriticalAssets() {
// 预加载关键样式和脚本
const criticalAssets = [
'/css/critical.css',
'/js/vendor.js'
];
criticalAssets.forEach(asset => {
const link = document.createElement('link');
link.rel = 'preload';
link.as = 'style';
link.href = asset;
document.head.appendChild(link);
});
}
2. 缓存策略
应用实例缓存
javascript
// 应用实例缓存管理
class AppInstanceCache {
constructor() {
this.cache = new Map();
this.maxCacheSize = 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,
lastAccessed: Date.now()
});
}
get(name) {
const cached = this.cache.get(name);
if (cached) {
cached.lastAccessed = Date.now();
return cached.instance;
}
return null;
}
delete(name) {
const cached = this.cache.get(name);
if (cached && cached.instance) {
// 正确卸载实例
if (cached.instance.unmount) {
cached.instance.unmount();
}
}
this.cache.delete(name);
}
clear() {
for (const [name, cached] of this.cache) {
this.delete(name);
}
}
}
const appCache = new AppInstanceCache();
错误处理和监控
1. 错误边界
微应用错误边界
javascript
// Vue 微应用错误处理
export async function mount(props) {
try {
app = new Vue({
router,
store,
render: h => h(App),
errorCaptured(err, vm, info) {
console.error('微应用组件错误:', err, info);
// 上报错误
reportError({
type: 'component_error',
error: err.message,
stack: err.stack,
component: vm?.$options.name,
info
});
// 返回 false 阻止错误继续向上传播
return false;
}
});
app.$mount(props.container ? props.container.querySelector('#app') : '#app');
} catch (error) {
handleError(error, 'mount');
}
}
function handleError(error, stage) {
console.error(`微应用${stage}阶段错误:`, error);
// 上报错误
reportError({
type: `micro_app_${stage}_error`,
error: error.message,
stack: error.stack,
stage
});
// 显示错误页面
const container = props.container || document.getElementById('app');
container.innerHTML = `
<div class="error-container">
<h3>应用加载失败</h3>
<p>请联系管理员或稍后重试</p>
<button onclick="location.reload()">重新加载</button>
</div>
`;
}
2. 性能监控
应用性能监控
javascript
// 性能监控工具
class PerformanceMonitor {
constructor() {
this.metrics = {};
}
startTracking(appName) {
this.metrics[appName] = {
startTime: performance.now(),
resources: [],
interactions: []
};
// 监控资源加载
if ('performance' in window) {
performance.getEntriesByType('resource').forEach(resource => {
this.metrics[appName].resources.push(resource);
});
}
}
endTracking(appName) {
if (this.metrics[appName]) {
const endTime = performance.now();
this.metrics[appName].endTime = endTime;
this.metrics[appName].totalTime = endTime - this.metrics[appName].startTime;
// 上报性能数据
this.reportPerformance(appName);
}
}
reportPerformance(appName) {
const metrics = this.metrics[appName];
if (metrics) {
// 发送性能数据到监控服务
fetch('/api/performance', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
app: appName,
totalTime: metrics.totalTime,
resourceCount: metrics.resources.length,
timestamp: Date.now()
})
});
}
}
}
const performanceMonitor = new PerformanceMonitor();
安全性考虑
1. 沙箱配置
安全的沙箱配置
javascript
// 主应用安全配置
start({
sandbox: {
// 启用严格的样式隔离
strictStyleIsolation: true,
// 启用实验性样式隔离(更安全)
experimentalStyleIsolation: true,
// 配置沙箱选项
speedy: false, // 关闭快速模式以提高安全性
},
// 配置加载选项
fetch: window.fetch, // 使用原生 fetch
});
2. 数据验证
输入验证
javascript
// 验证来自主应用的数据
function validateProps(props) {
const { userInfo, permissions } = props;
// 验证用户信息格式
if (userInfo && typeof userInfo === 'object') {
if (typeof userInfo.id !== 'number' || typeof userInfo.name !== 'string') {
throw new Error('Invalid user info format');
}
}
// 验证权限格式
if (permissions && Array.isArray(permissions)) {
if (!permissions.every(p => typeof p === 'string')) {
throw new Error('Invalid permissions format');
}
}
return true;
}
export async function mount(props) {
try {
validateProps(props);
// 安全地使用 props
app = new Vue({
router,
store: createStore(props.userInfo),
render: h => h(App),
});
app.$mount(props.container ? props.container.querySelector('#app') : '#app');
} catch (error) {
console.error('Props validation failed:', error);
throw error;
}
}
部署和运维
1. 版本管理
微应用版本控制
javascript
// 版本检测和兼容性检查
async function checkMicroAppVersion(appName, requiredVersion) {
try {
const response = await fetch(`${getAppEntry(appName)}/version.json`);
const versionInfo = await response.json();
if (!isVersionCompatible(versionInfo.version, requiredVersion)) {
console.warn(`微应用 ${appName} 版本不兼容: ${versionInfo.version} < ${requiredVersion}`);
// 可以选择降级或提示更新
return false;
}
return true;
} catch (error) {
console.error('版本检测失败:', error);
return false;
}
}
function isVersionCompatible(current, required) {
// 简单的版本比较逻辑
const currentParts = current.split('.').map(Number);
const requiredParts = required.split('.').map(Number);
for (let i = 0; i < requiredParts.length; i++) {
if (currentParts[i] > requiredParts[i]) return true;
if (currentParts[i] < requiredParts[i]) return false;
}
return true;
}
2. 灰度发布
渐进式部署
javascript
// 灰度发布控制
const GRAY_RELEASE_CONFIG = {
'user-center': {
enabled: true,
percentage: 30, // 30% 用户访问新版本
testUsers: ['admin', 'test'] // 指定测试用户
}
};
function shouldLoadNewVersion(appName, user) {
const config = GRAY_RELEASE_CONFIG[appName];
if (!config || !config.enabled) {
return true; // 默认加载新版本
}
// 检查是否为测试用户
if (config.testUsers.includes(user.name)) {
return true;
}
// 按百分比随机决定
return Math.random() * 100 < config.percentage;
}
// 根据灰度配置选择应用版本
function getAppEntry(appName, user) {
if (shouldLoadNewVersion(appName, user)) {
return getNewVersionEntry(appName);
} else {
return getOldVersionEntry(appName);
}
}
调试和开发工具
1. 开发时调试
调试工具集成
javascript
// 开发环境调试工具
if (process.env.NODE_ENV === 'development') {
// 启用 qiankun 开发工具
window.qiankunDevTools = {
getMicroApps: () => window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__,
getAppStatus: () => getMicroAppState(),
reloadApp: (appName) => {
// 重新加载指定微应用
return loadMicroApp(
getMicroAppConfig(appName),
getMicroAppProps(appName)
);
}
};
// 添加调试信息到控制台
console.log('qiankun dev tools enabled');
console.log('Available commands: window.qiankunDevTools');
}
通过遵循这些最佳实践,您可以构建出更加稳定、高效和安全的基于 qiankun 的微前端应用。