qiankun单个微应用集成的demo
这里改造的主应用和微应用都是Vue的项目,但是qiankun本身不限制技术栈,不同子应用可以是不同的技术栈,并且为了简单,方便大家搭建,这里的主微应用全部都是利用Vue-cli脚手架生成的。
0改造主应用
00创建微应用容器
微应用容器用于承载微应用,渲染显示微应用
test1
test2
//定义跳转方法
onChangePage(url){
console.log(url)
this.routerGo(url, '我喜爱的男明星')
},
routerGo(href = '/', title = null, stateObj = {}) {
window.history.pushState(stateObj, title, href);
}
出于简单考虑,这里没有使用router-view,防止因为路由的改变,主应用的渲染出现变化,现在这样做方便微应用挂载之后进行对比。
01注册微应用
微应用的注册点可以自己选择,既可以在main.js中进行注册,那么在应用启动时就会执行相应的生命周期函数,还可以在路由守卫中,命中路由之后进行注册,demo中选择在路由命中后动态的注册微应用。
//router/index.js
import { registerMicroApps, start } from "qiankun"
router.beforeEach((to, from, next) => {
if (to.path.includes('/chaiQiankunTest/ffff')) {
registerMicroApps(
[
{
name: "chai-project",//这里的name一定要和微应用这配置的output中的library相互对应,因为 name是主应用找到微应用对外暴露的生命周期函数的主要凭证
entry: "//localhost:8080",//这是微应用的入口地址
container: '#yourContainer',//这是在主应用中微应用的渲染承载容器
activeRule: "/chaiQiankunTest/ffff"//这是进行路由监听,一旦匹配,就会加载微应用并进行挂载,这里也要主要在微应用中需要设置路由base的时候要相互对应,后面会提到
}
],
{
beforeLoad: [
app => {
console.log("before load", app);
}
], // 挂载前回调
beforeMount: [
app => {
console.log("before mount", app);
}
], // 挂载后回调
afterUnmount: [
app => {
console.log("after unload", app);
}
] // 卸载后回调
}
)
start();
}
next();
})
01改造微应用
00导出 qiankun
主应用所需要的三个生命周期钩子函数
这里主要修改的就是微应用的入口文件main.js,由于代码不多,这里直接将整个文件代码贴出来
//main.js
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import routes from './router'
import axios from 'axios'
import Router from 'vue-router'
import './public-path'
let router = null;
let instance = null;
Vue.config.productionTip = false
Vue.use(Router);
/**
* 渲染函数
* 两种情况:主应用生命周期钩子中运行 / 微应用单独启动时运行
*/
function render (props) {
// 在 render 中创建 VueRouter,可以保证在卸载微应用时,移除 location 事件监听,防止事件污染
router = new Router({
// 运行在主应用中时,添加路由命名空间 /chaiQiankunTest/ffff,这和主应用中注册微应用时的activeRule相互对应
base: window.__POWERED_BY_QIANKUN__ ? 'chaiQiankunTest/ffff' : '/',
mode: 'history',
routes
});
// 挂载应用
instance = new Vue({
router,
render: (h) => h(App),
beforeCreate () {
window.util = {}
window.util.$http = axios.create({
timeout: 1000 * 50,
withCredentials: true
})
}
}).$mount('#app');
}
// 独立运行时,直接挂载应用
if (!window.__POWERED_BY_QIANKUN__) {
render();
}
/**
* bootstrap 只会在微应用初始化的时候调用一次,下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap。
* 通常我们可以在这里做一些全局变量的初始化,比如不会在 unmount 阶段被销毁的应用级别的缓存等。
*/
export async function bootstrap () {
console.log('mscrtApp bootstraped');
}
/**
* 应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法
*/
export async function mount (props) {
console.log('mscrtApp mount', props);
render(props);
}
/**
* 应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例
*/
export async function unmount () {
console.log('mscrtApp unmount');
instance.$destroy();
instance = null;
router = null;
}
//public-path.js
if (window.__POWERED_BY_QIANKUN__) {
// 动态设置 webpack publicPath,防止资源加载出错
// eslint-disable-next-line no-undef
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
这里面可能还牵扯到router/index.js的改造,将VueRouter的创建迁移到render中,具体的作用是可以保证在卸载微应用时,移除 location 事件监听,防止事件污染。
01配置 webpack
主要的目的是使 main.js
导出的生命周期钩子函数可以被 qiankun
识别获取 。
//webpack.base.conf.js
output: {
// 微应用的包名,这里与主应用中注册的微应用名称一致。这个名字也就是package.json中的name
library: 'chai-project',
// 将你的 library 暴露为所有的模块定义下都可运行的方式
libraryTarget: 'umd',
// 按需加载相关,设置为 webpackJsonp_VueMicroApp 即可
jsonpFunction: `webpackJsonp_chai-project`
},
//webpack.base.conf.js中的devServer对象中需要加入下面这个配置,这样主应用在fatch微应用静态资源时会出现跨域的问题
disableHostCheck: true,
headers: {
'Access-Control-Allow-Origin': '*'
}
如果没有设置这个跨域的设置,那么就可能出现跨域问题,
02demo演示
主应用界面初始化
test1和test2是两个触发注册微应用的按钮,功能一样,点击test1可以得到:
此时成功加载微应用,并且DOM结构为:
主应用和微应用的生命周期函数的执行顺序为
在点击回退到主应用的页面之后,主微应用的生命周期钩子函数的执行顺序为
总结
到这,Vue技术栈的主应用和微应用的集成Demo算是基本完成,这里只是最基础的一个集成示例,它们的钩子函数的执行顺序有些类似Vue中父子组件的生命周期函数的执行顺序。