一 主应用改造(又称基座改造)
1 在主应用中安装qiankun(npm i qiankun -S)
2 在src下新建micro-app.js文件,用于存放所有子应用。
const microApps = [
// 当匹配到activeRule 的时候,请求获取entry资源,渲染到container中
{
name: 'micro-vue3',
entry: '//localhost:40000',// 子应用的html入口
activeRule: '/vue1', // 路由匹配规则
container: '#micro-vue3', // 渲染到哪里
props: {},
},
];
export default microApps;
3 改造vue.config.js,允许跨域访问子应用页面
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
devServer: {
port: 8000,
headers: {
// 重点1: 允许跨域访问子应用页面
'Access-Control-Allow-Origin': '*',
},
},
})
4 改造main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router/router';
import ElementPlus from 'element-plus'; //element-plus
import 'element-plus/dist/index.css'; //element-plus
import { registerMicroApps, start } from 'qiankun';
import microApps from './micro-app';
// createApp(App).use(router).use(ElementPlus).mount('#app');
let app = createApp(App);
app.use(router);
app.use(ElementPlus);
app.mount('#app');
// 注册子应用
registerMicroApps(microApps, {
//还有一些生命周期 如果需要可以根据官网文档按需加入
beforeMount(app) {
console.log('挂载前', app);
},
afterMount(app) {
console.log('卸载后', app);
},
});
console.log("hello 主应用")
// 启动子应用
start({
prefetch: false, //取消预加载
sandbox: { experimentalStyleIsolation: true }, //沙盒模式
});
5 在App.vue中写响应跳转子应用(根据自己的项目找对应位置写,不局限于App.vue)
<template>
<el-menu :router="true" mode="horizontal">
<!-- 子应用的跳转路径 -->
<el-menu-item index="/index">主应用 main</el-menu-item>
<el-menu-item index="/vue1">子应用 vue3</el-menu-item>
</el-menu>
<!-- 主应用路由渲染出口 -->
<router-view />
<!-- 子应用的容器 -->
<!-- 微前端子应用渲染出口 -->
<div id="micro-vue3"></div>
</template>
<script>
export default {
name: 'App',
setup() {
return {};
},
};
</script>
<style>
html,
body,
#app {
width: 100%;
height: 100%;
margin: 0;
}
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #2c3e50;
}
</style>
需要注意这里的对应关系:
二 子应用改造
1 在src下新建public-path.js
if (window.__POWERED_BY_QIANKUN__) {
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
2 改造main
import { createApp } from 'vue'
import App from './App.vue'
import './public-path'; // 注意需要引入public-path
// createApp(App).mount('#app')
let instance = null;
console.log("hello 子应用")
function render({ container } = {}) {
instance = createApp(App);
// instance.use(router);
// instance.use(store);
instance.mount(container ? container.querySelector('#app2') : '#app2');
}
// 如何独立运行微应用?
if (!window.__POWERED_BY_QIANKUN__) {
render();
}
// 子应用接入 qiankun
// 1 导出三个必要的生命周期钩子函数
// bootstrap 渲染之前
// mount 渲染函数
// unmount 卸载函数
export async function bootstrap() {
// 启动
console.log("启动")
}
export async function mount() {
console.log("挂载")
// 挂载
render();
}
export async function unmount() {
// 例如从一个子应用到另一个子应用 需要先卸载后再加载,防止内存泄露
console.log("卸载")
// 卸载
instance.unmount();
instance = null;
// instance.$destroy();
// instance.$el.innerHTML = ''
// instance = null
}
3 改造vue.config.js
const { defineConfig } = require('@vue/cli-service')
const { name } = require('./package');
console.log("hello 子应用")
module.exports = defineConfig({
transpileDependencies: true,
devServer: {
port: 40000,
headers: {
'Access-Control-Allow-Origin': '*', //开发时增加跨域 表示所有人都可以访问我的服务器
},
},
configureWebpack: {
output: {
// 必须打包出一个库文件
library: `${name}-[name]`,
// 库格式必须是 umd
libraryTarget: 'umd', // 把子应用打包成 umd 库格式
// jsonpFunction: `webpackJsonp_${name}`,
chunkLoadingGlobal: `webpackJsonp_${name}`,
},
},
})
三 改造后效果