本地起主服务(vue3+webpack)和子服务vue3+vite+TS
主服务:安装qiankun
app.vue 添加子服务显示container
// 主服务app.vue
<template><div class="appMain"><router-view></router-view><div id="container"></div></div>
</template>
main.js 入口文件 注册子服务
// main.js
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import Antd from 'ant-design-vue';
import 'ant-design-vue/dist/reset.css';
import { registerMicroApps, start, setDefaultMountApp } from "qiankun";
import actions from './action.js'
import "@/assets/css/index.css";// let initialState = {
// name: "admin",
// userId: "admin001",
// };
// const { onGlobalStateChange, setGlobalState } = initGlobalState(initialState);
// onGlobalStateChange((state, prev) => {
// // state: 变更后的状态; prev 变更前的状态
// console.log(state, prev);
// });
// setGlobalState({
// age: 18
// }); // 用于修改全局状态的值
let arr = window.origin.split(":");
let origin = arr[0] + ":" + arr[1];
let apps = [{name: "brtv-web-system",entry: origin + ":9527",container: "#container",activeRule: "/brtv-web-system",},{name: "large_screen_lowcode",entry: origin + ":5173",container: "#container",activeRule: "/large_screen_lowcode",},// {// name: "vue3app2-webpack", // 对应子服务的package.josn的name// entry: "//localhost:3050", // 子服务入口// container: "#container", // 主服务配置的子服务容器// activeRule: "/vue3app2-webpack", // 子服务激活路由,主服务的link; 对应子服务路由模式basename// props: {// actions,// msg: '消息'// }// },
];
registerMicroApps(apps, {// qiankun 生命周期钩子 - 加载前beforeLoad: (app) => {console.log('加载子应用前,加载进度条=', app.name)// 退出方法// app.props.reRegister = () => {// store.dispatch('LogOut').then(() => {// sessionStorage.removeItem('tabViews')// location.reload()// console.log('重新登录~')// })// }return Promise.resolve()},// qiankun 生命周期钩子 - 挂载后afterMount: (app) => {console.log('加载子应用前,进度条加载完成', app.name)return Promise.resolve()}
});
const app = createApp(App);
app.use(router);
app.use(Antd); // size: 'large' | 'default' | 'small'
app.mount("#app");
// 设置主应用启动后默认进入的微应用。该方法接收一个string类型的参数,该参数为应用的basename。
// setDefaultMountApp('/brtv-web-system');
start({prefetch: false, // 禁用预加载//隔离样式sandbox sandbox: {// 开启严格的样式隔离模式。这种模式下 qiankun 会为每个微应用的容器包裹上一个 [shadow dom]节点,从而确保微应用的样式strictStyleIsolation: false,/** * strictStyleIsolation的坑:当启用strictStyleIsolation时,因为某些UI框架(例如element、ant-design等)可能会生成一些弹出框直接挂载到主应用的document.body下,此时由于脱离了shadow tree。会导致页面报错。设置实验性的样式隔离特性,即在子应用下面的样式都会包一个特殊的选择器规则来限定其影响范围* */experimentalStyleIsolation: true// 坑:动态类的弹窗样式丢失。子应用弹出框的样式不生效}
});// 页面重绘报错处理
const debounce = (fn, delay) => {let timer = null;return function () {let context = this;let args = arguments;clearTimeout(timer);timer = setTimeout(function () {fn.apply(context, args);}, delay);}
}const _ResizeObserver = window.ResizeObserver;
window.ResizeObserver = class ResizeObserver extends _ResizeObserver {constructor(callback) {callback = debounce(callback, 16);super(callback);}
}
子服务改造:
注意事项:现在安装vite适配乾坤的插件 vite-plugin-qiankun
1.子服务package.json 的name 对应 主服务注册子服务名称apps中的name
2.子服务router路由,使用history模式
import { createRouter, createWebHistory } from "vue-router";
import { qiankunWindow } from 'vite-plugin-qiankun/dist/helper';
const base = qiankunWindow.__POWERED_BY_QIANKUN__ ? '/large_screen_lowcode' : '/';
const router = createRouter({// 路由模式必须改为history模式,不然不生效history: createWebHistory(base),routes: [{path: '/',redirect: '/index'},{path: '/index',component: () => import('@/views/index.vue'),},{path: '/preview',component: () => import('@/views/preview.vue'),}]
})export default router
3.src根目录添加piblic-path.js
// 是否为微服务被使用
if (window.__POWERED_BY_QIANKUN__) {__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__
}
4.子服务入口文件main.ts 注册乾坤生命周期
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import zhCn from 'element-plus/es/locale/lang/zh-cn'
import router from "@/router";
import { createPinia } from "pinia";
import '@/lib/style.css';
import "./public-path.js";
import {renderWithQiankun,qiankunWindow,
} from "vite-plugin-qiankun/dist/helper";
const pinia = createPinia()let app: any;
// 判断是否在qiankun环境下
if (!qiankunWindow.__POWERED_BY_QIANKUN__) {createApp(App).use(ElementPlus, {locale: zhCn,}).use(pinia).use(router).mount('#app')
} else {renderWithQiankun({// qiankun的生命周期,挂载mount(props) {// 传递的值可以获取到了app = createApp(App);app.use(router);app.use(ElementPlus, {locale: zhCn,});app.use(pinia);app.mount(props.container? props.container.querySelector("#app"): document.getElementById("app"));},// 应用加载bootstrap() {console.log("--bootstrap");},// 修改update(props) {console.log("--update", props);},// 销毁unmount() {console.log("--unmount");app?.unmount();},});
}
// createApp(App).use(ElementPlus, {
// locale: zhCn,
// }).use(pinia).use(router).mount('#app')
5.修改vite.config.ts编译打包生成umd格式
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
import qiankun from "vite-plugin-qiankun";
const { name } = require('./package');
import { qiankunWindow } from 'vite-plugin-qiankun/dist/helper'
const baseUrl = qiankunWindow.__POWERED_BY_QIANKUN__ ? '/large_screen_lowcode' : '/';
// https://vite.dev/config/
export default defineConfig({base: baseUrl, //必须和基座也就是主应用的activeRule值一致server: {port: 5173, //端口号cors: true,headers: {"Access-Control-Allow-Origin": "*", //避免跨域},},plugins: [vue(),qiankun("large_screen_lowcode", {useDevMode: true,}),],optimizeDeps: {exclude: ['qiankun'],},resolve: {alias: {'@': resolve(__dirname, './src')}},// 在output中添加format: 'umd',打包成库格式build: {lib: {name: name, // 库的名称formats: ['umd', 'es'], // 支持的格式:umd和esentry: './src/main.ts', // 入口文件路径fileName: (format) => `name.${format}.js` // 输出文件名},rollupOptions: {// 确保外部化处理依赖external: ['vue'],output: {// 全局变量的名称globals: {vue: 'Vue'}}}}})