故事的开始
在一个风和日丽的下午,我正喝着女神请的9.9咖啡,逛着掘金摸着🐟,一切的一切都是这么的美好。
霎那间,只见耳边响起了声音,"系统觉醒中,请。。",啊?我都外挂到账了?
呸,是"帅哥,领导叫你去开会"。
"哦",某位帅哥站了起来,撇了撇帅气的刘海,走向了办公室。
会议室情节
"咦,不是开会吗,怎么就只有领导一个人"。
昏暗的灯光,发着亮光的屏幕,在幽闭的空间里气氛显得有那么一丝的~~~暧昧,不对,是紧张。
"帅哥你来了,那我直接说事情吧",领导说到。
突然我察觉到那么一丝不安,但是现在走好像来不及了,房门紧闭,领导又有三头六臂,凭着我这副一米八五,吴彦祖的颜值的身躯根本就逃不了。
"是这样的,上面有个新需求,我看完之后发现我们目前的项目技术包袱有点重,做起来比较麻烦,看看你做个项目技术栈升级提高的方案吧"。
听到这里我松了一口气,还好只是升级提高的方案,不是把屁股抬高的方案。
进入正题
分析了公司项目当前的技术栈,确实存在比较杂乱的情况,一堆的技术包袱,惨不忍睹,但还是能跑的,人和项目都能跑。
技术栈:vue2全家桶 + vuetify + 某位前辈自己开发的组件库 + 某位前辈搞的半成品bff
我用了一分钟的时间做足了思想功课,这次的升级决定采用增量升级的方案,为什么用增量升级,因为线上的项目,需求还在开发,为了稳定和尽量少的投入人力,所以采取增量升级。
这里会有很多小伙伴问,什么是增量升级啊,我会说,自己百度
又经过了一分钟的思想斗争,决定使用微前端的方案进行技术升级,框架选择阿里的qiankun
。
这里又会有小伙伴说,为什么用qiankun啊,我会说,下面会说
微前端---qiankun
为什么使用微前端,最主要是考虑到他与技术栈无关,能够忽略掉一些历史的包袱。
为什么要用qiankun,最主要还是考虑到稳定问题,qiankun目前的社区比较大,方案也多,出了问题能找到方案,本人之前也有使用过的经验,所以这次就决定是它。
技术为业务服务,在面对技术选型的时候要考虑到现实的问题,不能一味的什么都用新的,稳是第一位
那么应该如何在老项目中使用微前端去升级,我给出了我的方案步骤
- 对老项目进行改造(路由,登录,菜单)
- 编写子应用的开发模板
- 逐个逐个模块进行重构
下面会和大家分析一下三个步骤的内容
老项目的改造(下面大多数为代码)
第一步,我们要将老项目改造成适合被子应用随便进入的公交车。🚗
先对老项目进行分析,老项目是一个后台项目,大多数的后台项目布局都是上中左布局,头部导航栏,左边菜单栏,中间内容。那么我们只需要当用户选择的菜单属于微前端模块时,将中间内容变成微前端容器就好了。
那我们现在制作一个layout
,里面的UI库我懒得换了,讲究看吧🌈
js
// BasicLayout.vue
<a-layout>
<a-layout-sider collapsible>
//菜单
</a-layout-sider>
<a-layout>
<a-layout-header>
//头部
</a-layout-header>
<a-layout-content>
//内容
<router-view/>
<slot></slot>
</a-layout-content>
</a-layout>
</a-layout>
然后对App.vue进行一定的修改
js
// App.vue
<a-config-provider locale="zh-cn">
<component v-if="layout" :is="layout">
<!-- 微前端子应用的容器,插槽紧跟着view-router -->
<div id="SubappViewportWrapper"></div>
</component>
// 初始化子应用时传入容器,这个容器不能后续修改,目前方案是将下面的容器动态append到SubappViewportWrapper
<div id="SubappViewport"></div>
</a-config-provider>
import { BasicLayout, UserLayout } from '@/layouts'
import { MICRO_APPS } from './qiankun'
import { start } from 'qiankun';
export default defineComponent({
components: {
BasicLayout,
UserLayout
},
data () {
return {
locale: zhCN,
layout: ''
}
},
methods: {
isMicroAppUrl (url) {
let result = false;
MICRO_APPS.forEach(mUrl => {
if (url.includes(mUrl)) {
result = true;
}
});
return result;
},
checkMicroApp (val) {
if (isMicroAppUrl(val.fullPath)) {
// 展示微前端容器
console.log('是微前端应用....');
document.body.classList.toggle(cName, false);
console.log(document.body.classList);
} else {
// 隐藏微前端容器
console.log('不是微前端应用');
document.body.classList.toggle(cName, true);
}
const oldLayout = this.layout;
this.layout = val.meta.layout || 'BasicLayout';
if (oldLayout !== this.layout) {
const cNode = document.getElementById('SubappViewport');
this.$nextTick(function () {
const pNode = document.getElementById('SubappViewportWrapper');
if (pNode && cNode) {
pNode.appendChild(cNode);
}
});
}
}
},
watch: {
$route (val) {
this.checkMicroApp(val);
}
},
mounted () {
start()
}
})
</script>
<style lang="less">
</style>
修改目的,判断路由中是否为微前端模块,如果是的话,就插入微前端模块容器。
然后新建一个qiankun.js
文件
js
// qiankun.js
import { registerMicroApps, initGlobalState } from 'qiankun';
export const MICRO_APPS = ['test-app']; // 子应用列表
const MICRO_APPS_DOMAIN = '//localhost:8081'; // 子应用入口域名
const MICRO_APP_ROUTE_BASE = '/test-app'; // 子应用匹配规则
const qiankun = {
install (app) {
// 加载子应用提示
const loader = loading => console.log(`加载子应用中:${loading}`);
const registerMicroAppList = [];
MICRO_APPS.forEach(item => {
registerMicroAppList.push({
name: item,
entry: `${MICRO_APPS_DOMAIN}`,
container: '#SubappViewport',
loader,
activeRule: `${MICRO_APP_ROUTE_BASE}`
});
});
// 注册微前端应用
registerMicroApps(registerMicroAppList);
// 定义全局状态
const { onGlobalStateChange, setGlobalState } = initGlobalState({
token: '', // token
});
// 监听全局变化
onGlobalStateChange((value, prev) => {
console.log(['onGlobalStateChange - master'], value);
});
}
};
export default qiankun;
这个文件我们引入了qiankun
并对使用它的API进行子应用的注册,之后直接在main.js
注册,
js
// main.js
...
import qiankun from './qiankun'
Vue.use(qiankun)
...
然后我们只需要对路由做一点点的修改就可以用了
新建RouteView.vue
页面,用于接受微前端模块的内容
js
//RouteView.vue
<template>
<router-view v-slot="{ Component }">
<component :is="Component" />
</router-view>
</template>
修改路由配置
js
//router.js
const routes = [
{
path: '/home',
name: 'Home',
meta: {},
component: () => import('@/views/Home.vue')
},
// 当是属于微前端模块的路由, 使用RouteView组件
{
path: '/test-app',
name: 'test-app',
meta: {},
component: () => import('@/RouteView.vue')
}
]
最后就新增一个名为test-app
的子应用就可以了。
关于子应用的内容,这次先不说了,码字码累了,下次再说吧。
下集预告(子应用模板编写)
你们肯定会说,不要脸,还搞下集预告。
哼,我只能说,今天周五,准备下班,不码了。🌈