Skip to content

乾坤微应用

官方文档

主应用

使用的 vue3 框架

1. 安装依赖

sh
 yarn add qiankun

2. 注册微应用并启动

js
// main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import { registerMicroApps, start } from 'qiankun'

let app = createApp(App)
app.use(router)
app.mount('#app')
// 在主应用中注册子应用
registerMicroApps([
{
name: 'vueApp', //微应用的名称,有多个微应用的话,必须保证唯一
entry: '//localhost:8088', // 本地运行后子应用的访问地址
container: '#container', // 微应用插入的位置
activeRule: '/app-vue', // 微应用访问入口
props: {}, //传给微应用的数据
},
{
name: 'reactApp',
entry: '//localhost:3000',
container: '#container',
activeRule: '/app-react',
},
])
// 启动 要等主页面加载完毕才能启动,即nextTick之后启动
// sandbox: { experimentalStyleIsolation: true }开启沙箱隔离样式
start(sandbox: { experimentalStyleIsolation: true })

registerMicroApps 包含两个参数, 第一个是子应用的配置信息, 第二个参数全局的微应用生命周期钩子

js
registerMicroApps(apps, {
  beforeLoad: (app) => {
    // 加载微应用前,加载进度条
    NProgress.start();
    console.log("before load", app.name);
    return Promise.resolve();
  },
  afterMount: (app) => {
    // 加载完微应用,进度条加载完成
    NProgress.done();
    console.log("after mount", app.name);
    return Promise.resolve();
  },
});

3. 提供微应用挂载容器

vue
<!-- App.vue -->
<template>
  <div>
    <router-view />
    <!-- 微应用的容器 -->
    <div id="container"></div>
  </div>
</template>

4. 配置导航菜单

html
<div>
  <router-link to="/app-vue/home">vue子应用</router-link>
  <router-link to="/app-react/about">react子应用</router-link>
</div>

子应用

创建一个 vue3 项目

1. 配置 publicPath

src 目录下新建 public-path.js 文件

js
if (window.__POWERED_BY_QIANKUN__) {
  // eslint-disable-next-line  no-undef
  __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}

2. 修改入口文件

引入 public-path 文件, 导出bootstrapmountunmount三个生命周期函数, 以供主应用在适当的时机调用

js
// main.js
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import "./public-path";

let app = null;
function render(props = {}) {
  const { container } = props;
  app = createApp(App);
  app.use(router);
  app.mount(container ? container.querySelector("#app") : "#app");
}
// 微应用独立运行时,直接挂载应用
if (!window.__POWERED_BY_QIANKUN__) {
  render();
}
/**
 * bootstrap 只会在微应用初始化的时候调用一次
 *下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap
 */
export async function bootstrap() {
  console.log("%c%s", "color: green;", "vue3.0 app bootstraped");
}
/**
 * 应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法
 */
export async function mount(props) {
  render(props);
}
/**
 * 应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例
 */
export async function unmount() {
  app.unmount();
  app = null;
  router.options.history.destroy();
}

3. 打包文件配置

为了让主应用能正确识别微应用暴露出来的一些信息,微应用的打包工具需要增加如下配置

js
// vue.config.js
const { defineConfig } = require("@vue/cli-service");
const packageName = require("./package.json").name;

module.exports = defineConfig({
  //...
  configureWebpack: {
    output: {
      // 微应用的包名,与主应用中注册的微应用名称一致
      library: `${packageName}-[name]`,
      libraryTarget: "umd", // 把微应用打包成 umd 库格式
      jsonpFunction: `webpackJsonp_${packageName}`,
    },
  },
});

应用间通信

主应用中使用 initGlobalState 设置全局状态 actions 并导出供其他组件使用

js
// main.js
import { initGlobalState, MicroAppStateActions } from "qiankun";

// 初始化数据
const state = {};
const actions = initGlobalState(state);
actions.setGlobalState(state);

微应用中在生命周期 mount 中, 通过 props 获取

js
// 从生命周期 mount 中获取通信方法,使用方式和 master 一致
export function mount(props) {
  props.onGlobalStateChange((state, prev) => {
    // state: 变更后的状态; prev 变更前的状态
    console.log(state, prev);
  });

  props.setGlobalState(state);
}