前提精要
本篇文章不会告诉你微前端应用的底层原理,我了解其中的部分底层原理,但是展开来说的话过于繁琐。所以本篇文章会专注于如何使用微前端以及为什么要使用微前端,还有就是微前端解决了我们哪些方面的问题
微前端技术基于【腾讯无界】搭建:github.com/Tencent/wuj...
应用背景
我们目前存在多个跨端应用,大部分跨端应用都是用pyqt做的。并且pyqt做的跨端应用对于数据导出的流程也一直没有经过规范化。导致已经编写过的代码不能够进行下次复用,就增加了开发人员的开发成本。为了避免此类重复的问题出现。我写的软件应该提供一个本地导出中台,并且使得同局域网内部的其他软件能够方便的使用web侨接技术来方便的调用医疗图像工作站软件提供的导出中台。减少工程师的重复开发成本。
微前端概念
当我们编写一个前台应用的时候,我们不止是在编写一个网页,我们其实也是在编写一个服务的入口,那么这就涉及到一个问题,就是计算机中一个端口只能提供一个给入口。如果说你想要在你的服务器上尽可能多的给用户提供交互服务的话,那么你就要占用多个端口。然后多个端口再暴露出来多个入口。这样的话使用人员可能要记录多个端口,并且在浏览器开多个进程去执行任务。有没有一种技术能够使得一个应用能够集成多种应用的服务,并且将这些服务提供的交互都整合到一起,然后再暴露出去?有的,这种技术叫做微前端技术
微前端数据基站
我们会存在一个项目,这个项目会整合其他的软件项目,然后用户访问前端提供的软件服务走的端口也会是这个软件服务的端口。这个项目的作用就是对通过微前端技术注册在旗下的其他子路由项目做路由劫持。然后统一将这些子项目的应用服务保存在一个统一的用户界面里面给用户去使用。拥有以上功能的项目叫做基站项目。
arduino
// 生产环境处理
const map:any = {
"//localhost:3000": "/childApps/exportpdf"
}
export default function hostMap(host:string){
if (process.env.NODE_ENV === "production") return map[host]
return host
}
typescript
// 注册应用生命周期
const lifecycles = {
beforeLoad: (appWindow:any) => console.log(`${appWindow.__WUJIE.id} beforeLoad 生命周期`),
beforeMount: (appWindow:any) => console.log(`${appWindow.__WUJIE.id} beforeMount 生命周期`),
afterMount: (appWindow:any) => console.log(`${appWindow.__WUJIE.id} afterMount 生命周期`),
beforeUnmount: (appWindow:any) => console.log(`${appWindow.__WUJIE.id} beforeUnmount 生命周期`),
afterUnmount: (appWindow:any) => console.log(`${appWindow.__WUJIE.id} afterUnmount 生命周期`),
activated: (appWindow:any) => console.log(`${appWindow.__WUJIE.id} activated 生命周期`),
deactivated: (appWindow:any) => console.log(`${appWindow.__WUJIE.id} deactivated 生命周期`),
loadError: (url:string, e:any) => console.log(`${url} 加载失败`, e),
};
export default lifecycles;
typescript
// 注册子应用
const isProduction = process.env.NODE_ENV === "production";
const attrs = isProduction ? { src: hostMap("//localhost:3000/") } : {};
const degrade = window.localStorage.getItem("degrade") === "true" || !window.Proxy || !window.CustomElementRegistry;
const props = {
jump: (name:string) => {
router.push({ name });
},
}
setupApp({
name: 'export-pdf',
url: hostMap("//localhost:3000/"),
attrs,
exec: true,
props,
degrade,
...lifecycles,
})
基站应用注册子应用
在上面的案例中,我们将子应用定义到了3000端口,然后我们只需要启动3000端口的应用,我们就可以将子应用集成到我们的系统之上去了。
应用与应用之前的互相通信
单向通信,父应用向子应用分发数据:
ini
<WujieVue
width="100%"
height="100%"
name="exportpdf"
:props="subAppProps"
:url="appUrl"
:sync="true"
>
</WujieVue>
const subAppProps=ref({
name: 'PDF子应用',
desc: "一个从主基站中分发出来的子应用"
})
子应用接受父应用数据
xml
<template>
<div class="export-content">
这里是PDF工具
</div>
</template>
<script lang="ts" setup>
import {onMounted} from 'vue'
onMounted(()=>{
receiveParentAppData()
})
const receiveParentAppData=()=>{
console.log(window.$wujie?.props)
}
</script>
<style lang="scss" scoped>
.export-content{
width: 100%;
height: 100%;
background-color: red;
}
</style>
重点在于Props。但是这种通信是单向的,在子应用和父应用之间,可能存在双向的通信,这里无界提供了一个自带的eventBus。
eventBus双向通信:
javascript
const {bus} = WujieVue
const handlerSend = ()=>{
bus.$emit("imageinfo", "你好世界")
}
javascript
const registerEventBus = ()=>{
window.$wujie?.bus.$on("imageinfo", function (str) {
console.log(str)
});
}