Skip to content
On this page

qiankun 速查表

核心 API

主要函数

javascript
import { 
  registerMicroApps,  // 注册微应用
  start,             // 启动 qiankun
  loadMicroApp,      // 动态加载微应用
  initGlobalState    // 初始化全局状态
} from 'qiankun';

基本用法

javascript
// 注册微应用
registerMicroApps([
  {
    name: 'app1',
    entry: '//localhost:3001',
    container: '#container',
    activeRule: '/app1',
    props: { data: 'from main' }
  }
], {
  // 生命周期钩子
  beforeLoad: app => console.log('loading', app.name),
  beforeMount: app => console.log('mounting', app.name),
  afterMount: app => console.log('mounted', app.name),
  beforeUnmount: app => console.log('unmounting', app.name),
  afterUnmount: app => console.log('unmounted', app.name)
});

// 启动 qiankun
start({
  prefetch: true, // 预加载
  sandbox: {
    strictStyleIsolation: true, // 严格样式隔离
    experimentalStyleIsolation: false
  }
});

微应用生命周期

完整生命周期

javascript
let app = null;

// 启动时调用一次
export async function bootstrap(props) {
  console.log('应用启动', props);
}

// 每次进入时调用
export async function mount(props) {
  console.log('应用挂载', props);
  
  const { container } = props;
  
  // 根据框架创建应用实例
  app = new Vue({
    router,
    store,
    render: h => h(App),
  }).$mount(container ? container.querySelector('#app') : '#app');
}

// 每次切出/卸载时调用
export async function unmount(props) {
  console.log('应用卸载', props);
  
  if (app) {
    app.$destroy();
    app.$el.innerHTML = '';
    app = null;
  }
}

// 可选的更新钩子(使用 loadMicroApp 时)
export async function update(props) {
  console.log('应用更新', props);
}

通信机制

全局状态通信

javascript
// 主应用 - 初始化全局状态
import { initGlobalState } from 'qiankun';

const { onGlobalStateChange, setGlobalState, getGlobalState } = initGlobalState({
  user: { id: 1, name: 'admin' },
  theme: 'dark'
});

// 监听全局状态变化
onGlobalStateChange((state, prev) => {
  console.log('全局状态变化', state, prev);
}, true); // true 表示立即触发一次

// 微应用 - 使用全局状态
export async function mount(props) {
  const { onGlobalStateChange, setGlobalState, getGlobalState } = props;
  
  // 监听状态变化
  onGlobalStateChange((state, prev) => {
    console.log('微应用监听到状态变化', state, prev);
  });

  // 修改全局状态
  setGlobalState({
    user: { ...getGlobalState().user, lastVisit: Date.now() }
  });
}

Props 通信

javascript
// 主应用传递数据
registerMicroApps([
  {
    name: 'app1',
    entry: '//localhost:3001',
    container: '#container',
    activeRate: '/app1',
    props: {
      // 传递的数据
      userInfo: { id: 1, name: 'John' },
      theme: 'dark',
      // 传递方法
      onMainEvent: (data) => {
        console.log('微应用触发主应用事件', data);
      }
    }
  }
]);

// 微应用接收数据
export async function mount(props) {
  const { userInfo, theme, onMainEvent } = props;
  
  console.log('接收到的用户信息:', userInfo);
  console.log('接收到的主题:', theme);
  
  // 调用主应用方法
  onMainEvent({ message: '来自微应用的消息' });
}

配置选项

start() 配置

javascript
start({
  prefetch: true,           // 启用预加载
  // prefetch: ['app1'],    // 预加载指定应用
  // prefetch: false,       // 禁用预加载
  
  sandbox: {
    // 沙箱配置
    strictStyleIsolation: true,      // 严格样式隔离
    experimentalStyleIsolation: true, // 实验性样式隔离
    type: 'legacy',                  // 沙箱类型: 'legacy' | 'proxy' | 'snapshot'
  },
  
  // 生命周期钩子
  beforeLoad: app => console.log('加载前', app.name),
  beforeMount: app => console.log('挂载前', app.name),
  afterMount: app => console.log('挂载后', app.name),
  beforeUnmount: app => console.log('卸载前', app.name),
  afterUnmount: app => console.log('卸载后', app.name),
});

registerMicroApps 配置

javascript
registerMicroApps([
  {
    name: 'app1',                    // 应用名称
    entry: '//localhost:3001',      // 应用入口
    container: '#container',         // 挂载容器
    activeRule: '/app1',            // 激活规则
    // activeRule: location => location.pathname.startsWith('/app1'),
    
    props: {                        // 传递给微应用的属性
      data: 'some data',
      callback: () => console.log('callback')
    }
  }
], {
  // 全局生命周期钩子
  beforeLoad: app => {},
  beforeMount: app => {},
  afterMount: app => {},
  beforeUnmount: app => {},
  afterUnmount: app => {}
});

动态加载

loadMicroApp 使用

javascript
import { loadMicroApp } from 'qiankun';

// 动态加载微应用
const microApp = await loadMicroApp(
  {
    name: 'dynamic-app',
    entry: '//localhost:3001',
    container: '#dynamic-container',
  },
  {
    sandbox: {
      strictStyleIsolation: true,
    },
    props: {
      data: 'from parent'
    }
  }
);

// 监听微应用状态
microApp.onGlobalStateChange((state) => {
  console.log('微应用状态变化', state);
});

// 卸载微应用
await microApp.unmount();

构建配置

Webpack 配置

javascript
// webpack.config.js
module.exports = {
  output: {
    library: 'microApp',        // 微应用名称
    libraryTarget: 'umd',       // 输出格式
    jsonpFunction: `webpackJsonp_microApp`, // 避免冲突
    publicPath: '//localhost:3001/' // 静态资源路径
  },
  devServer: {
    headers: {
      'Access-Control-Allow-Origin': '*' // 支持跨域
    },
    port: 3001
  }
};

Vite 配置

javascript
// vite.config.js
import { defineConfig } from 'vite';

export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        format: 'umd',
        entryFileNames: '[name].js',
        chunkFileNames: '[name].js',
        assetFileNames: '[name].[ext]'
      }
    }
  },
  server: {
    cors: true,
    port: 3001
  }
});

常用工具函数

工具函数

javascript
import { isMicroApp, getMicroAppState } from 'qiankun';

// 检查是否在微应用环境中
const isInMicroApp = window.__POWERED_BY_QIANKUN__;

// 检查微应用是否激活
if (isMicroApp()) {
  console.log('当前在微应用环境中');
}

// 获取微应用状态
const appState = getMicroAppState();

// 创建路由适配器
function createMicroRouter(baseHistory, microRouter) {
  if (window.__POWERED_BY_QIANKUN__) {
    // 微前端环境下使用主应用的 history
    return microRouter;
  }
  return microRouter;
}

常见问题解决

样式隔离问题

javascript
// 启用样式隔离
start({
  sandbox: {
    strictStyleIsolation: true, // 严格样式隔离
    // 或
    experimentalStyleIsolation: true // 实验性样式隔离
  }
});

// CSS Modules 方式
// 在微应用中使用命名空间
.container[data-qiankun="app1"] {
  .component {
    color: blue;
  }
}

路由冲突解决

javascript
// 微应用路由配置
export async function mount(props) {
  const { container, routerBase = '/sub-app' } = props;
  
  const router = new VueRouter({
    mode: 'history',
    base: routerBase, // 使用传递的基础路径
    routes: [
      { path: '/', component: Home },
      { path: '/page', component: Page }
    ]
  });
  
  app = new Vue({ router }).$mount(container.querySelector('#app'));
}

跨域问题解决

javascript
// 微应用 webpack 配置
module.exports = {
  devServer: {
    headers: {
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
      'Access-Control-Allow-Headers': 'X-Requested-With, content-type, Authorization'
    }
  }
};

性能优化

预加载策略

javascript
start({
  prefetch: {
    // 关键应用立即预加载
    criticalAppList: [
      { name: 'critical-app', entry: '//localhost:3001' }
    ],
    // 非关键应用空闲时预加载
    idleAppList: [
      { name: 'idle-app', entry: '//localhost:3002' }
    ],
  }
});

// 或使用函数自定义预加载逻辑
start({
  prefetch: (apps) => {
    // 自定义预加载逻辑
    return apps.filter(app => 
      app.status !== 'failed' && 
      shouldPrefetch(app)
    );
  }
});

资源优化

javascript
// 微应用代码分割
// webpack.config.js
module.exports = {
  optimization: {
    splitChunks: {
      chunks: 'all',
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          chunks: 'all'
        }
      }
    }
  }
};

调试技巧

开发环境调试

javascript
// 启用调试模式
if (process.env.NODE_ENV === 'development') {
  window.__QIANKUN_DEVELOPMENT__ = true;
}

// 检查 qiankun 状态
console.log('qiankun loaded:', window.__POWERED_BY_QIANKUN__);

// 手动加载微应用(调试用)
const { loadMicroApp } = require('qiankun');
loadMicroApp({
  name: 'test-app',
  entry: '//localhost:3001',
  container: '#container'
});

// 检查全局状态
const { initGlobalState } = require('qiankun');
const state = initGlobalState({});
console.log('global state:', state);

最佳实践

项目结构

main-app/                 # 主应用
├── src/
│   ├── micro-apps/      # 微应用注册配置
│   ├── layouts/         # 布局组件
│   └── main.js
└── package.json

micro-apps/             # 微应用目录
├── user-center/        # 用户中心微应用
│   ├── src/
│   └── package.json
├── product-center/     # 产品中心微应用
└── order-center/       # 订单中心微应用

错误处理

javascript
// 主应用错误处理
window.addEventListener('error', (e) => {
  console.error('Micro app error:', e);
});

window.addEventListener('unhandledrejection', (e) => {
  console.error('Unhandled promise rejection:', e);
});

// 微应用错误处理
export async function mount(props) {
  try {
    // 应用初始化逻辑
  } catch (error) {
    console.error('Micro app mount failed:', error);
    // 通知主应用错误
    if (props.onError) {
      props.onError(error);
    }
  }
}

常用代码片段

Vue 微应用模板

javascript
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';

let app = null;

export async function bootstrap(props) {
  console.log('Vue app bootstrap', props);
}

export async function mount(props) {
  console.log('Vue app mount', props);
  
  const { container } = props;
  
  app = createApp(App);
  app.use(router);
  app.use(store);
  app.mount(container ? container.querySelector('#app') : '#app');
}

export async function unmount(props) {
  console.log('Vue app unmount', props);
  
  if (app) {
    app.unmount();
    app = null;
  }
}

// 独立运行支持
if (!window.__POWERED_BY_QIANKUN__) {
  createApp(App).use(router).use(store).mount('#app');
}

React 微应用模板

javascript
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import App from './App';

let app = null;

export async function bootstrap(props) {
  console.log('React app bootstrap', props);
}

export async function mount(props) {
  console.log('React app mount', props);
  
  const { container } = props;
  
  app = (
    <BrowserRouter>
      <App />
    </BrowserRouter>
  );
  
  ReactDOM.render(
    app,
    container ? container.querySelector('#root') : document.getElementById('root')
  );
}

export async function unmount(props) {
  console.log('React app unmount', props);
  
  if (app) {
    ReactDOM.unmountComponentAtNode(
      props.container ? props.container.querySelector('#root') : document.getElementById('root')
    );
    app = null;
  }
}

// 独立运行支持
if (!window.__POWERED_BY_QIANKUN__) {
  ReactDOM.render(<App />, document.getElementById('root'));
}

这份速查表涵盖了 qiankun 的核心概念、API 使用、配置选项、常见问题解决和最佳实践,可作为快速参考指南使用。