Vue3 微前端 qiankun 配置说明

437 阅读1分钟

主应用配置

安装依赖包

$ yarn add qiankun # 或者 npm i qiankun -S

注册微应用

// src/config/microAppConfig.js

const {publicPath, devPath} = require("../../web.config");
const getActiveRule = (activeRule) => (location) => location.pathname.startsWith(`${publicPath}${activeRule}`);
export default [
    {
        name: 'vueApp',
        entry: `${devPath}:3000`,
        container: '#microAppContainer',
        activeRule: getActiveRule('/s-app'),
        routerPath: '/s-app'
    },
]

// src/layout/layoutPage/index.vue

<template>
	<div id="microAppContainer" class="single-spa-vue"></div>
</template>

import {initGlobalState, registerMicroApps, runAfterFirstMounted, start} from "qiankun";
import microAppConfig from "@/config/microAppConfig";

mounted() {
    /**
     * 注册子应用
     */
    registerMicroApps(microAppConfig, {
        beforeLoad: [
            app => {
                console.log('[LifeCycle] before load %c%s', 'color: green;', app.name);
            },
        ],
        beforeMount: [
            app => {
                console.log('[LifeCycle] before mount %c%s', 'color: green;', app.name);
            },
        ],
        afterUnmount: [
            app => {
                console.log('[LifeCycle] after unmount %c%s', 'color: green;', app.name);
            },
        ],
    },);
    const {onGlobalStateChange, setGlobalState} = initGlobalState({
        user: 'qiankun',
    });
    onGlobalStateChange((value, prev) => console.log('[onGlobalStateChange - master]:', value, prev));
    setGlobalState({
        ignore: 'master',
        user: {
            name: 'master',
        },
    });
    /**
     * 启动应用
     */
    start();
    runAfterFirstMounted(() => {
        console.log('[MainApp] first app mounted');
    });
}

修改路由切换点击事件

// src/layout/layoutPage/aside/LeftMenu.vue

onMenuClick(e) {
    let toPath = this.pathObject[e.key];
    const {path} = this.$route;
    if (path !== toPath) {
        history.pushState(null, null, toPath);
    }
},

注册微应用路由配置

// src/router/module/spa.router.js

import VueView from "@/layout/VueView";
import microAppConfig from "@/config/microAppConfig";

const spaRouters = microAppConfig.map(v => {
    return {
        path: v.routerPath,
        component: VueView,
        meta: {requireLogin: true}
    }

})
export default spaRouters;

Vue 微应用

  1. src 目录新增 public-path.js
if (window.__POWERED_BY_QIANKUN__) {
    // eslint-disable-next-line no-undef
    __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
  1. 入口文件 main.js 修改,为了避免根 id #app 与其他的 DOM 冲突,需要限制查找范围。
import './public-path';
import {createApp} from 'vue';
import {createRouter, createWebHashHistory,} from 'vue-router';
import App from './App.vue';
import routes from './router';
import store from './store';

let router = null;
let instance = null;
let history = null;

function render(props = {}) {
    const {container} = props;
    history = createWebHashHistory();
    router = createRouter({
        history,
        routes,
    });

    instance = createApp(App);
    instance.use(router);
    instance.use(store);
    instance.mount(container ? container.querySelector('#app') : '#app');
}

if (!window.__POWERED_BY_QIANKUN__) {
    render();
}

export async function bootstrap() {
    console.log('%c ', 'color: green;', 'vue3.0 app bootstraped');
}

function storeTest(props) {
    props.onGlobalStateChange &&
    props.onGlobalStateChange(
        (value, prev) => console.log(`[onGlobalStateChange - ${props.name}]:`, value, prev),
        true,
    );
    props.setGlobalState &&
    props.setGlobalState({
        ignore: props.name,
        user: {
            name: props.name,
        },
    });
}

export async function mount(props) {
    storeTest(props);
    render(props);
    instance.config.globalProperties.$onGlobalStateChange = props.onGlobalStateChange;
    instance.config.globalProperties.$setGlobalState = props.setGlobalState;
}

export async function unmount() {
    instance.unmount();
    instance._container.innerHTML = '';
    instance = null;
    router = null;
    history.destroy();
}
  1. 打包配置修改(vue.config.js):
const { name } = require('./package');
module.exports = {
  devServer: {
    headers: {
      'Access-Control-Allow-Origin': '*',
    },
  },
  configureWebpack: {
    output: {
      library: `${name}-[name]`,
      libraryTarget: 'window',
      jsonpFunction: `webpackJsonp_${name}`,
    },
  },
};