WuJie无界微前端使用和问题解决

我正在参加「金石计划5.0」

一、WuJie无界微前端

1.WuJie说明

说明文档:wujie-micro.github.io/doc/guide/

微前端是一种多个团队通过独立发布功能的方式来共同构建现代化 web 应用的技术手段及方法策略。

通俗来说,就是在一个web应用中可以独立的运行另一个web应用

微前端有什么使用场景呢?

举例

  • 比如制作一个企业管理平台,把已有的采购系统和财务系统统一接入这个平台;
  • 比如有一个巨大的应用,为了降低开发和维护成本,分拆成多个小应用进行开发和部署,然后用一个平台将这些小应用集成起来;
  • 又比如一个应用使用vue框架开发,其中有一个比较独立的模块,开发者想尝试使用react框架来开发,等模块单独开发部署完,再把这个模块应用接回去

可能有人会有疑问直接使用iframe不就可以做到吗?

采用iframe的方案确实可以做到,而且优点非常明显

优点

  • 非常简单,使用没有任何心智负担
  • web应用隔离的非常完美,无论是jscssdom都完全隔离开来

由于其隔离的太完美导致缺点也非常明显

缺点

  • 路由状态丢失,刷新一下,iframeurl状态就丢失了
  • dom割裂严重,弹窗只能在iframe内部展示,无法覆盖全局
  • web应用之间通信非常困难
  • 每次打开白屏时间太长,对于SPA 应用来说无法接受

WuJie无界的方案,就是为了解决iframe存在的问题,而且还能带来更多的优势,详情可以查看WuJie无界官方指导文档。

2.WuJie快速上手

2.1主应用

1.安装wujie依赖

bash 复制代码
# vue2 框架
npm i wujie-vue2 -S

# vue3 框架
# npm i wujie-vue3 -S

注意:使用vue的框架,是2还是3

2.main.js引入wujie

javascript 复制代码
//引入无界微前端
// vue2
import WujieVue from "wujie-vue2";
// vue3
// import WujieVue from "wujie-vue3";

import lifecycles from "../config/lifecycle";
const { setupApp, preloadApp, bus } = WujieVue;
Vue.use(WujieVue);
const props = {
    jump: (name) => {
        router.push({ name });
    },
};

//设置子应用demo
setupApp({
    name: "demo",
    url: "/demo/home/index",
    exec: true,
    props,
    fetch: function fetch(url, options) {
        //console.log("fetch.url:=",url,options)
        return window.fetch(url, { ...options, credentials: "omit" });
    },
    ...lifecycles,
});

// 预加载
//preloadApp({
//    name: "demo",
//});

注意:setupApp 设置子应用的namepreloadApp 设置的name要一致。

预加载,可以极大的提升子应用首次打开速度

  • 资源的预加载会占用主应用的网络线程池
  • 资源的预执行会阻塞主应用的渲染线程
    一般来说,如果不是很介意打开的首屏时间,这里预加载可以不用加。
  • lifecycle.js
javascript 复制代码
const lifecycles = {
    beforeLoad: (appWindow) => console.log(`${appWindow.__WUJIE.id} beforeLoad 生命周期`),
    beforeMount: (appWindow) => console.log(`${appWindow.__WUJIE.id} beforeMount 生命周期`),
    afterMount: (appWindow) => console.log(`${appWindow.__WUJIE.id} afterMount 生命周期`),
    beforeUnmount: (appWindow) => console.log(`${appWindow.__WUJIE.id} beforeUnmount 生命周期`),
    afterUnmount: (appWindow) => console.log(`${appWindow.__WUJIE.id} afterUnmount 生命周期`),
    activated: (appWindow) => console.log(`${appWindow.__WUJIE.id} activated 生命周期`),
    deactivated: (appWindow) => console.log(`${appWindow.__WUJIE.id} deactivated 生命周期`),
    loadError: (url, e) => console.log(`${url} 加载失败`, e),
};
export default lifecycles;

这个是生命周期函数

无界提供一整套的生命周期钩子供开发者调用

如果子应用没有做生命周期的改造,那么 beforeMount、afterMount、beforeUnmount、afterUnmount 这四个生命周期将不会调用

2.2子应用

子应用改造,无界对子应用的侵入非常小,在满足跨域条件下子应用可以不用改造

子应用的资源和接口的请求都在主域名发起,所以会有跨域问题。

所以这里,主应用和子应用,建议使用nginx进行代理,解决跨域的问题。

php 复制代码
//主应用
location /main {
    proxy_set_header Host    $host;
    proxy_pass http://127.0.0.1:8080;
}

//子应用
location /demo {
    proxy_set_header Host    $host;
    proxy_pass http://127.0.0.1:8081;
}
  • 运行模式

无界有三种运行模式:单例模式保活模式重建模式

其中保活模式重建模式子应用无需做任何改造工作,单例模式需要做生命周期改造

改造入口函数:

  • 将子应用路由的创建、实例的创建渲染挂载到window.__WUJIE_MOUNT函数上
  • 将实例的销毁挂载到window.__WUJIE_UNMOUNT
  • 如果子应用的实例化是在异步函数中进行的,在定义完生命周期函数后,请务必主动调用无界的渲染函数 window.__WUJIE.mount()
  • vue2
javascript 复制代码
if (window.__POWERED_BY_WUJIE__) {
  let instance;
  window.__WUJIE_MOUNT = () => {
    const router = new VueRouter({ routes });
    instance = new Vue({ router, render: (h) => h(App) }).$mount("#app");
  };
  window.__WUJIE_UNMOUNT = () => {
    instance.$destroy();
  };
} else {
  new Vue({ router: new VueRouter({ routes }), render: (h) => h(App) }).$mount("#app");
}
  • vue3
ini 复制代码
if (window.__POWERED_BY_WUJIE__) {
  let instance;
  window.__WUJIE_MOUNT = () => {
    const router = createRouter({ history: createWebHistory(), routes });
    instance = createApp(App);
    instance.use(router);
    instance.mount("#app");
  };
  window.__WUJIE_UNMOUNT = () => {
    instance.unmount();
  };
} else {
  createApp(App).use(createRouter({ history: createWebHistory(), routes })).mount("#app");
}

注意:使用vue的框架,是2还是3

2.3wujie使用

经过上面主应用和子应用的改造之后,就可以再主应用中,使用wujie,将子应用引入到主应用中去。

主应用,有这样的一个vue组件

  • wujieDemo.vue 页面使用WujieVue引用目标项目的页面
xml 复制代码
<template> 
    <WujieVue
            width="100%"
            height="100%"
            name="demo"
            :url="demoUrl"
        />
</template>
​
<script>
 export default {
  data() {
    return {
        demoUrl: '/demo/home/index',
    }
  },
</script>

注意,上面 WujieVue 使用的name要和 setupApp 设置的name,要对应。

3.集成问题处理

3.1 window.parent问题

如果你集成的子应用中,也有用到iframe,那么在iframe中,使用window.parent,这个获取到的,不再是子应用了,这个window.parent将会是主应用

出现这个问题,就是你可能会将一些对象,放入到window里面,那这个时候,需要兼容下这个情况。

例如:

ini 复制代码
window.Demo = {}

//这个时候,需要再加上
window.parent.Demo = window.Demo; //这个的作用,是将Demo这个对象赋值给 "主应用"

这样,在iframe中,使用window.parent.demo,就不会出现null的问题了。

3.2 antdv出现message不显示问题

出现这个问题,是在第一次打开子应用后,关闭后,重新再打开子应用。message消息提示框,无法显示。

出这个问题,是因为子应用,进行了生命周期改造导致。

所以这里,不建议对子应用进行生命周期改造。

...

还有很多问题,不知道怎么解决,也解决不了,最后还是放弃了...

4.写在最后

由于在整合的时候,遇到了不少问题,最后还是放弃了这个方式。

改用回iframe的方式,世界瞬间都清净了。

wujie你强任你强,我放弃了,放手一撑,与世无争


好了,以上就是我个人的实操了。可能有些不对,大家伙,轻点喷!!!

个人理解,可能也不够全面,班门弄斧了。

好了,今天就先到这里了!!!^_^

如果觉得有收获的,帮忙点赞、评论、收藏一下,再走呗!!!

相关推荐
咖啡の猫22 分钟前
Shell脚本-for循环应用案例
前端·chrome
百万蹄蹄向前冲3 小时前
Trae分析Phaser.js游戏《洋葱头捡星星》
前端·游戏开发·trae
朝阳5813 小时前
在浏览器端使用 xml2js 遇到的报错及解决方法
前端
GIS之路3 小时前
GeoTools 读取影像元数据
前端
ssshooter4 小时前
VSCode 自带的 TS 版本可能跟项目TS 版本不一样
前端·面试·typescript
Jerry5 小时前
Jetpack Compose 中的状态
前端
dae bal5 小时前
关于RSA和AES加密
前端·vue.js
柳杉5 小时前
使用three.js搭建3d隧道监测-2
前端·javascript·数据可视化
lynn8570_blog6 小时前
低端设备加载webp ANR
前端·算法
LKAI.6 小时前
传统方式部署(RuoYi-Cloud)微服务
java·linux·前端·后端·微服务·node.js·ruoyi