vue create qiankun-base
npm install vue-router@4
npm i qiankun -S
import { registerMicroApps,runAfterFirstMounted,addGlobalUncaughtErrorHandler } from 'qiankun';
registerMicroApps( [{
name: 'app1',
entry: 'http://localhost:8081/',
container: '#container',
activeRule:'app1'
}], {
beforeLoad: [app => {
return Promise.resolve();
}]
}
)
runAfterFirstMounted(() => {
console.log('子应用加载完毕')
})
/**
2. 补取异常
*/
addGlobalUncaughtErrorHandler((event) => {
const { message } = event;
// 加载失败时提示
if (message && message .includes("died in status LOADING_SOURCE_CODE")) {
console.log("微应用加载失败_"+msg);
}
});
<div id="container"></div>
onMounted(() => {
if (!window.qiankunStarted) {
window.qiankunStarted = true;
start({
prefetch: true, // 开启预加载
sandbox: {
experimentalStyleIsolation: true,
},
});
}
});
)
补充:想要主应用访问子应用中的某一个页面,代码做出以下修改
registerMicroApps( [{
name: 'app1',
entry: 'http://localhost:8081/',
container: '#container',
activeRule:'app1/login' // 访问子应用的login页面
}], {
beforeLoad: [app => {
return Promise.resolve();
}]
}
)
{
path: '/app1/:pathMatch(.*)',
name: 'app1',
component: () => import('../views/qiankunEntry.vue'),
}
<template>
<div id="container"></div>
</template>
<script>
import { start } from 'qiankun';
import { reactive, toRefs, ref, onMounted } from "vue";
export default {
setup() {
onMounted(() => {
start({
prefetch: false, // 开启预加载
sandbox: {
experimentalStyleIsolation: true,
}
});
})
}
}
</script>
提示:补充的2、3步来设置容器使用更方便,不用考虑样式对#container的影响,也可以避免不需要加载子应用时#container对于已有页面造成影响
注意:这里的container不能添加在启动的页面会报错:Target container with #container not existed while son loading!
特别注意:这里的路由要用createWebHistory,要不然会导致qiankun不能启动!
提示:子应用不需要安装qiankun
vue create qiankun-app
npm install vue-router@4
if (window.__POWERED_BY_QIANKUN__) {
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
注意:这里需要在package.json下面新增配置globals
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "@babel/eslint-parser"
},
"rules": {},
"globals": {
"__webpack_public_path__": true
}
}
注意:要注意这里routes写法,上会报错:Loading chunk src_views_homeView_vue failed.
const routes = [{
path: '/',
name: 'homeView',
component: import('../views/homeView.vue')
}]
这样是不对的,需要用下面这种写法
import homeView from '../views/homeView.vue'
const routes = [{
path: '/',
name: 'homeView',
component: homeView
}]
可能跟vue3的路由加载机制有关
import {
createRouter,
createWebHistory
} from 'vue-router';
import routes from './router'
let router = null;
let instance = null;
let history = null;
function render(props = {}) {
const {
container
} = props;
history = createWebHistory(window.__POWERED_BY_QIANKUN__ ? `${props.name}` : '/');
router = createRouter({
history,
routes,
});
instance = createApp(App);
instance.use(router);
instance.mount(container ? container.querySelector('#app') : '#app');
}
// 本地调试
if (!window.__POWERED_BY_QIANKUN__) {
render()
}
// 生命周期 - 挂载前,在这里由主应用传过来的参数
export async function bootstrap() {
// console.log('one bootstrap'+JSON.stringify(props))
console.log(localStorage.getItem('test'));
}
// 生命周期 - 挂载后
export async function mount(props) {
render(props)
// // 主应用传递过来的 props.fn 是一个对象。循环遍历下,将各个属性绑定到子应用的原型链上
// Object.keys(props.fn).forEach(method => {
// createApp.prototype[`$${method}`] = props.fn[method]
// })
// 渲染
}
// 生命周期 - 解除挂载
export async function unmount() {
instance.unmount();
instance._container.innerHTML = '';
instance = null;
router = null;
history.destroy();
}
const { name } = require('./package.json')
module.exports = {
devServer: {
port: 8081,
headers: {
'Access-Control-Allow-Origin': '*'
}, proxy: {
'/api4': {
target: 'http://127.0.0.1',
changeOrigin: true,
ws: true,
pathRewrite: { '^/api4': '' }
}
}
},
configureWebpack: {
output: {
library: `${name}-[name]`,
// 把子应用打包成umd库格式
// 当我们把 libraryTarget 设置为 umd 后,我们的 library 就暴露为所有的模块定义下都可运行的方式 了,主应用就可以获取到微应用的生命周期钩子函数了
libraryTarget: 'umd',
jsonpFunction: `webpackJsonp_${name}`
}
}
}
使用createWebHistory路由模式的时候会有页面刷新报错的问题,可以在vue.config.js中设置publicPath
publicPath: process.env.NODE_ENV === 'development' ? '/' : '/',
参考链接: vue3.0+乾坤实现微应用
打包发布的部分还没有测试,后续继续补充