由于主应用微应用都能做到技术栈无关,不论是 React/Vue/Angular/JQuery 还是其他等框架,这里使用的主应用微应用均使用vue2,前端路由模式为hash模式。
1.主应用下载qiankun
npm i qiankun -S
2.在主应用src文件夹下创建main-app.js
以下micorApps就是子应用,可以配置多个子应用,但是子应用挂载的div是相同的,记住这个 container: '#test-web'
const microApps = [
{
name: 'test-web', // 子应用名称
entry: 'http://localhost:8088/', //子应用运行地址
activeRule: '#/test-web',//匹配的路由 hash模式前加 # history模式不用加
singular: true, // 启用单实例模式
},
]
const apps = microApps.map(item => {
return {
...item,
container: '#test-web', // 子应用挂载的div
props: {
routerBase: item.activeRule // 下发基础路由
}
}
})
export default apps
3.在主应用main.js中导入main-app.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
Vue.config.productionTip = false
import { registerMicroApps, start } from 'qiankun';
import mainApp from './main-app'
registerMicroApps(mainApp, {
beforeLoad: app => {
console.log('before load app.name====>>>>>', app.name)
},
beforeMount: [
app => {
console.log('[LifeCycle] before mount %c%s', 'color: green;', app.name)
}
],
afterMount: [
app => {
console.log('[LifeCycle] after mount %c%s', 'color: green;', app.name)
}
],
afterUnmount: [
app => {
console.log('[LifeCycle] after unmount %c%s', 'color: green;', app.name)
}
]
})
start()
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
4.配置主应用路由
在主应用src文件夹下添加qiankun文件夹,并且添加index.vue文件作为入口文件
注意!!!这里的id:test-web要和main-app.js中 container: '#test-web', 名字一致,不然报错
<template>
<div id="test-web"></div>
</template>
<script>
export default {
mounted() {},
};
</script>
<style scoped>
#test-web {
width: 100%;
height: 100%;
}
/* 定义qiankun高为100%,不然的话高度不匹配 */
/deep/ #__qiankun_microapp_wrapper_for_test_web__{
height: 100%;
}
</style>
在router文件夹下注册qiankun路由
注意!!path: "/test-web/*",路由的名字要和上面的 activeRule:名字一致
import layout from '../qiankun/index.vue'
import Vue from "vue";
import VueRouter from 'vue-router'
import layout from '../qiankun/index.vue'
Vue.use(VueRouter)
const routes = [
{
path: "*",
name: "404",
redirect: "/404"
},
{
path: "/",
name: "Login",
redirect: "/login"
},
{
path: "/login",
name: "Login",
meta: { title: "登录" },
component: () => import("../components/Login")
},
{
path: "/test-web/*",
meta: 'test-web',
component: layout
},
]
const router = new VueRouter ({
mode: 'hash',
base: process.env.BASE_URL,
routes
})
export default router;
到此主应用程序配置完毕
5.在子应用main.js文件添加如下代码
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
Vue.config.productionTip = false
// new Vue({
// router,
// store,
// render: h => h(App)
// }).$mount('#app')
// 判断是否在qiankun的运行环境下,非qiankun运行环境下单独运行
if (window.__POWERED_BY_QIANKUN__) {
// eslint-disable-next-line no-undef
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
let instance = null;
function render(props = {}) {
const { container } = props;
console.log(11111111111111, window.__POWERED_BY_QIANKUN__, '字段值')
instance = new Vue({
router,
store,
render: h => h(App),
}).$mount(container ? container.querySelector('#app') : '#app', true); //开启沙箱
}
export default instance
if (!window.__POWERED_BY_QIANKUN__) {
console.log('独立运行')
render();
}
function storeTest(props) {
props.onGlobalStateChange &&
props.onGlobalStateChange(
(value, prev) => console.log(`[onGlobalStateChange - ${props.name}]:`, value, prev),
true,
);
props.setGlobalState &&
props.setGlobalState({
ignore: props.name,
user: {
name: props.name,
},
});
}
// 各个生命周期,只会在微应用初始化的时候调用一次,下次进入微应用重新进入是会直接调用mount钩子,不会再重复调用bootstrap
export async function bootstrap() {
console.log('111111111111 [vue] vue app bootstraped');
}
// 应用每次进入都会调用mount方法,通常在这里触发应用的渲染方法
export async function mount(props) {
console.log('11111111111 [vue] props from main framework', props);
storeTest(props);
render(props);
}
// 应用每次切除/注销会调用的方法,在这里会注销微应用的应用实例
export async function unmount() {
instance.$destroy();
instance.$el.innerHTML = '';
instance = null;
}
6.注册子应用路由
import Vue from 'vue'
import VueRouter from 'vue-router'
import HomeView from '../views/HomeView.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/about',
name: 'about',
component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
},
{
path: "/test-web/nenergyOperation/teamManage/personnelManage",
name: "人员管理",
meta: { title: "人员管理" },
component: () => import("@/views/nenergyOperation/teamManage/personnelManage")
},
]
const router = new VueRouter ({
mode: 'hash',
base: window.__POWERED_BY_QIANKUN__ ? '/test-web/' : '/',
routes
})
export default router
注意!!path: "/test-web/nenergyOperation/teamManage/personnelManage"
在你的子应用路由路径前面添加 /test-web,不然主应用跳转微应用的时候找不到路径
7.在子应用webpack.base.conf.js文件里面配置
module.exports = {
context: path.resolve(__dirname, '../'),
entry: { //编译打包的入口文件 main.js
app: './src/main.js'
},
output: { //出口文件
// 以下三行是为qiankun框架配置
library: 'test-web', //这个'test-web'名称必须与主应用main-app.js文件里面配置的子应用名称一致,不然会报错!!
libraryTarget: 'umd',
jsonpFunction: `webpackJsonp_${name}`,
path: config.build.assetsRoot, //
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
}
}
这边需要注意!webpack版本5.0以下改为:jsonpFunction: `webpackJsonp_${name}`
webpack5.0以上: chunkLoadingGlobal: `webpackJsonp_${name}`
library: 'test-web', //这个'test-web'名称必须与主应用main-app.js文件里面配置的子应用名称一致,不然会报错!!
运行端口8081要和主应用配置mian-app.js文件的 entry: 'http://localhost:8081/', //子应用运行地址一致,不然获取不到子应用内容
8.在子应用webpack.dev.conf.js文件中配置
devServer: {
clientLogLevel: 'warning',
historyApiFallback: {
rewrites: [
{ from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
],
},
hot: true,
contentBase: false, // since we use CopyWebpackPlugin. 打开不运行在src下
compress: true,
host: HOST || config.dev.host,
port: PORT || config.dev.port,
open: config.dev.autoOpenBrowser,
overlay: config.dev.errorOverlay
? { warnings: false, errors: true }
: false,
publicPath: config.dev.assetsPublicPath,
proxy: config.dev.proxyTable,
quiet: true, // necessary for FriendlyErrorsPlugin
watchOptions: {
poll: config.dev.poll,
},
headers:{'Access-Control-Allow-Origin':'*'} //*开发环境下解决qiankun跨域问题*
},
headers:{'Access-Control-Allow-Origin':'*'} //*开发环境下解决qiankun跨域问题*
到这里就结束了,此时运行主应用跳转路由就跳转到子应用了,在子应用做更改主应用同时就会更新,并且主应用与子应用分别独立开发,独立部署,实现微前端开发。