1、主应用
- 安装乾坤
npm i qiankun -S
- 注册微应用并启动:
import { registerMicroApps, start } from 'qiankun';
//设置两个微应用
registerMicroApps([
{
name: 'vue1', //要跟package.json中的name保持一致
entry: '//localhost:8081', //本地就这么写
container: '#container', //主应用id
activeRule: '/app-vue1', //这个值必须跟子应用中路由的base一致
},
{
name: 'vue2',
entry: '//localhost:8082',
container: '#container2', //可以在主应用的其他div上挂在微应用
activeRule: '/app-vue2',
}
]);
// 启动 qiankun
start();
2、微应用
- 在
src
目录新增public-path.js
//public-path.js
if (window.__POWERED_BY_QIANKUN__) {
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
- 设置
history
模式路由的base
//router.js
const router = new VueRouter({
base: window.__POWERED_BY_QIANKUN__ ? '/app-vue1' : '', //base中的'/app-vue1'要和主应用中的activeRule一致
mode: 'history', //建议使用history模式
routes: baseRoutes //子应用路由地址
})
修改main.js
入口文件
//main.js
import './public-path';
import Vue from 'vue';
import VueRouter from 'vue-router';
import App from './App.vue';
import routes from './router';
import store from './store';
Vue.config.productionTip = false;
let router = null;
let instance = null;
function render(props = {}) {
const { container } = props;
router = new VueRouter({
base: window.__POWERED_BY_QIANKUN__ ? '/app-vue/' : '/',
mode: 'history',
routes,
});
instance = new Vue({
router,
store,
render: (h) => h(App),
}).$mount(container ? container.querySelector('#datacenter') : '#datacenter'); //此处的#datacenter要跟index.html中的id保持一致
}
// 独立运行时
if (!window.__POWERED_BY_QIANKUN__) {
render();
}
export async function bootstrap() {
console.log('[vue] vue app bootstraped');
}
export async function mount(props) {
console.log('[vue] props from main framework', props);
render(props);
}
export async function unmount() {
instance.$destroy();
instance.$el.innerHTML = '';
instance = null;
router = null;
}
修改index.html中的#app
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<!-- 避免id冲突,修改#app -->
<div id="datacenter"></div>
</body>
</html>
修改vue.config.js配置
//vue.config.js
const { name } = require('./package'); //从package.json中获取name
module.exports = {
devServer: {
headers: {
'Access-Control-Allow-Origin': '*',
},
},
configureWebpack: {
output: {
library: `${name}-[name]`, // 微应用的包名,这里与主应用中注册的微应用名称一致
libraryTarget: 'umd', // 把微应用打包成 umd 库格式
jsonpFunction: `webpackJsonp_${name}`, // 按需加载相关,设置为 webpackJsonp_微应用名称 即可
},
},
};
3、路由配置
主应用的路由一定要和微应用保持一致
//主应用
{
path: '/personalCenter', // personalCenter为例
name: 'personalCenter',
component: () => import('@/views/personalCenter/index'),
meta: {
title: '个人中心',
},
},
//微应用
{
path: '/personalCenter/*', // personalCenter为基路由。*表示通配,这个一定要配置
name: 'personalCenter',
component: () => import('@/views/personalCenter/index'),
meta: {
title: '个人中心',
},
},
4、上线常见问题
1、设置域名之后,最外层的ng必须请求主应用的ng,再用主应用的ng请求子应用的ng,否则刷新会白屏
2、主应用打包的域名要和子应用的域名对应上,否则跳转不了
3、动态路由主应用跳转子应用需要重新获取一次路由
4、刷新路由丢失,需要在主子应用routerberforEach中重新获取一次路由
// 路由守卫
export function matchRouteMenu(to: Route, from: Route, next: NavigationGuardNext<Vue>) {
const accessToken = UserModule.token || Cookies.get(TokenKey)
console.log('to.path',from, to,accessToken)
if (accessToken) {
if (to.path === '/login') {
next({ path: '/index' })
} else {
if (from.path == '/') {
UserModule.getMenu(getAppCode())
}
next()
}
} else {
if (process.env.NODE_ENV === 'thirdparty') next('/404') // 接入公车
if (to && to.path && ['/login', '/404', '/505', '/403'].indexOf(to.path) !== -1) {
next()
} else {
next('/login')
}
}
}