前言
很久没更新了,说忙也在忙,说不忙也在划! 最近公司需要搭建一个新的项目框架,把之前的系统做整合,让我使用ifram搞,果断拒绝,给他安利无界微应用。虽然之前只是在自己项目中跑,没在实际中用过。那既然没用过,那肯定得用,开搞!
主应用搭建
使用 vite 脚手架进行 vue3 项目搭建。在之前的文章中有相关的介绍,就不再赘述juejin.cn/post/720499… 走完上面的流程默认vu3项目已经可以运行
主应用改造
安装wujie
"wujie-vue3": "^1.0.18"
在 main.ts
中 引入 WujieVue
并使用 setupApp
进行子应用设置
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'
import WujieVue from 'wujie-vue3'
const { setupApp } = WujieVue
import { micros, getUrl } from '@/utils'
import lifecycles from './lifecycles' // 生命周期函数
const app = createApp(App)
const render = () => {
app.use(createPinia())
app.use(router)
app.use(WujieVue)
app.mount('#app')
}
render()
// 模拟接口查询,实现动态子应用加载与动态路由添加
const setMiro = () =>
new Promise((resolve) => {
for (const value of micros) {
const obj: any = {
path: `/${value.name}`,
name: value.name,
component: () => import(`@/views/micro/index.vue`) //子应用使用同一个wujie配置
}
router.addRoute('home', obj)
setupApp({
name: value.name,
url: getUrl(value.name, micros),
exec: true,
...lifecycles
})
}
resolve(true)
})
// eslint-disable-next-line require-await
router.beforeEach(async (to, _from, next) => {
if (router.getRoutes().length <= 3) {
// 如果路由个数为基础路由,则说明没有进行路由和子应用添加,需要动态添加,添加完成,根据路由地址进行跳转
await setMiro()
next({
path: to.path,
query: { ...to.query }
})
} else {
next()
}
})
lifecycles.ts
引入,暂时函数里面还用不到,先放着
const lifecycles = {
beforeLoad(appWindow: any) {
// 第一次子应用的时候执行
// 打开加载动画
},
beforeMount() {
// console.log('beforeMount()-----------------');
},
afterMount(appWindow: any) {
// 自应用第一次挂载到页面上之后执行(后续会缓存,不会执行)
// 关闭加载动画
},
beforeUnmount(appWindow: any) {
// console.log('beforeUnmount()-----------------');
},
afterUnmount(appWindow: any) {
// console.log('afterUnmount()-----------------');
},
activated(appWindow: any) {
// console.log(appWindow)
},
deactivated(appWindow: any) {
// console.log('deactivated()-------------------------');
}
}
export default lifecycles
micros
为我们定义的子应用,也是顶部的tab,切换tab,跳转相应的子应用;getUrl
根据传值过来的name,进行子应用路径返回。如,我们切换到数据规则tab 时,url
返回//localhost:8001/data-rule/
。当发布线上时,因为部署在统一域名端口下,所有直接取对应的路径 /data-rule/
export const micros = [
{
name: 'data-rule',
desc: '数据规则',
port: 8001
},
{
name: 'event-rule',
desc: '事件规则',
port: 8002
}
]
export const getUrl = (appName: string, mciroList = micros) => {
const config = mciroList.find((item) => item.name === appName)
if (import.meta.env.MODE === 'development') {
return `//localhost:${config.port}/${config.name}/`
}
return `/${config.name}/`
}
动态加载路由的页面需要引入 wujie
alive
为true 保活状态 sync
页面刷新依旧保持在当前页面
<template>
<div class="sub-app">
<WujieVue width="100%" height="100%" :name="name" :url="url" :alive="true" sync />
</div>
</template>
<script lang="ts" setup>
import { getUrl } from '@/utils'
const router: any = useRouter()
const url = computed(() => getUrl(router.currentRoute.value.name))
const name = computed(() => router.currentRoute.value.name)
</script>
<style scoped lang="scss">
.sub-app {
height: 100%;
width: 100%;
.wujie_iframe {
height: 100%;
}
}
</style>
子应用改造
子应用改造比较简单
在 main.ts 中加入无界判断
import './assets/main.css'
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'
const app = createApp(App)
const render = () => {
app.use(createPinia())
app.use(router)
// console.log(app._context.components)
app.mount('#app')
}
declare global {
interface Window {
// 是否存在无界
__POWERED_BY_WUJIE__?: boolean
// 子应用mount函数
__WUJIE_MOUNT: () => void
// 子应用unmount函数
__WUJIE_UNMOUNT: () => void
// 子应用无界实例
__WUJIE: { mount: () => void }
$wujie: any
}
}
if (window.__POWERED_BY_WUJIE__) {
// console.log(window.$wujie)
window.__WUJIE_MOUNT = () => {
render()
}
window.__WUJIE_UNMOUNT = () => {
app.unmount()
}
window.__WUJIE.mount()
} else {
render()
}
在路由配置中添加路径
例如data-rule 子应用
vite.config.ts 修改打包路径与本地运行端口
base
为我们打包后项目运行根路径
port
为本地运行端口
outDir
根据个人需要,看是否需要修改输出位置。(输出放一块的话,在nginx发布方便)
放一下demo效果,切换tab 更换子应用
总结一下
实现一个微应用,主要需要对主应用进行改造,引入无界,配置子应用端口,与路由路径,实现子应用跳转。子应用如果在满足跨域的情况下可以不用改造。附上代码仓库 gitee.com/Provens/mic…
无界学习地址 wujie-micro.github.io/doc/guide/s…
下一步计划
将打包项目部署在服务器,进行真实场景添加,子应用跳转,主应用子应用数据传参等,引入外部子应用(不同域下,ng转发等)。