背景

需要将多个已有业务系统集成到云平台,统一登录统一身份认证, 。不涉及前端依赖共用。

基本使用,基于vue2

主应用安装qiankun
1
2
npm i qiankun -s  或者
yarn add qiankun
主应用引入qiankun,注册子应用,启动qiankun。

main.js中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { registerMicroApps, start } from 'qiankun'

const apps = [{
name: 'maintain_index',
entry: 'http://192.168.1.8:8084', // 子应用地址
container: '#yw-maintain-index-container', // 子应用挂载在主应用的元素
activeRule: '/maintain_index', // 进入子应用的路由标识
props: {
container: 'identity' // 参数
}
}]

registerMicroApps(apps); //注册子应用
start(); //启动qiankun
改造子应用

在我这个需求场景中,这个子应用也是其他子应用的主应用,所以它既是主也是子,所以它也要安装qiankun,如果是从主应用进入的,则在主应用启动本应用后,再启动本应用的子应用
main.js中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
let instance = null;
function render(props = {}) {
// 如果是从主应用进来的,则可能有参数,如果单独运行则没有
const { container } = props;
instance = new Vue({
router,
render: h => h(App),
}).$mount(container ? container.querySelector('#app') : '#app');
}

//判断当前运行环境是独立运行的还是在父应用里面进行运行,配置全局的公共资源路径
if (window.__POWERED_BY_QIANKUN__) {
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__
}
//如果是独立运行window.__POWERED_BY_QIANKUN__=undefined
if (!window.__POWERED_BY_QIANKUN__) {
const apps = [{
name: 'kettle',
entry: 'http://192.168.1.8:8083',
container: '#yw-kettle-container',
activeRule: '/kettle',
props: {
container1: 'main'
}
}]
registerMicroApps(apps); //注册子应用
start(); //启动qiankun
render()
}

//最后暴露的三个方法是固定的,加载渲染以及销毁,这是生命周期的3个节点,暴露出去供主应用调用
export async function bootstrap(props = {}) {
// 如果被qiankun包裹,则在主应用启动本应用后,再启动本应用的子应用
const apps = [{
name: 'kettle',
entry: 'http://192.168.1.8:8083',
container: '#yw-kettle-container',
activeRule: '/maintain_index/kettle',
props: {
container1: props.container
}
}]
registerMicroApps(apps); //注册子应用
start();
}
export async function mount(props) {
render(props);
}
export async function unmount() {
instance.$destroy();
}
改造子应用的子应用

mian.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
let instance = null;

function render(props = {}) {
// router要在这里写,在router的js文件中还获取不到window.__POWERED_BY_QIANKUN__的变化
// 本应用是第三级应用,所以需要判断是从第一级开始启动的,还是直接运行的第二级,还是直接单独运行的本应用,然后加对应的路由前缀
// window.__KETTLE_BOX__是在启动本应用时由主应用传入的参数
const router = new VueRouter({
routes,
base: window.__KETTLE_BOX__==='identity' ? '/maintain_index/kettle' : (window.__POWERED_BY_QIANKUN__ ? '/kettle' : '/'),
mode: 'history',
})
// router.beforeEach也就需要在router声明后才能使用, 可以优化代码书写方式

// 这里模拟了动态路由
window.ls = false
router.beforeEach(async(to, from, next) => {
if (window.ls) {
next()
} else {
setTimeout(() => {
window.ls = true
router.addRoutes([{
path: '/layout',
name: 'layout',
component: window.__POWERED_BY_QIANKUN__ ? Layout1 : Layout,
children: [{
path: '/Music',
name: 'Music',
component: Music
}]
}])
next({
...to,
replace: true
})
}, 1000)
}
})
router.afterEach(() => {
})

const { container } = props;
instance = new Vue({
router,
// store,
render: h => h(App),
}).$mount(container ? container.querySelector('#app') : '#app');
}

//判断当前运行环境是独立运行的还是在父应用里面进行运行,配置全局的公共资源路径
if (window.__POWERED_BY_QIANKUN__) {
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__
}
//如果是独立运行window.__POWERED_BY_QIANKUN__=undefined
if (!window.__POWERED_BY_QIANKUN__) {
render()
}
//最后暴露的三个方法是固定的,加载渲染以及销毁
export async function bootstrap(props = {}) {
// 将最外层的基座传进来
window.__KETTLE_BOX__ = props.container1
}
export async function mount(props) {
render(props);
}
export async function unmount() {
instance.$destroy();
}

vue.config.js
子应用配置跨域,本地开发调试的时候才能正确被主应用访问

1
2
3
4
5
6
7
8
9
10
devServer: {
port: 8083,
headers: {
"Access-Control-Allow-Origin": "*", // 配置跨域
"Access-Control-Allow-Headers": "*",
"Access-Control-Allow-Credentials": "true",
"Access-Control-Allow-Methods": "*",
"Cache-Control": "no-cache",
}
}

至此,3个vue2项目都可以单独运行,也可以以微前端形式运行了。qiankun是基于single-spa封装的,使用了html-entry,相比2019年写single-spa的demo时简单了不止一点。