基于 wujie.js 进行微前端融合

项目背景

目前项目中需要将A ,B 两个项目进行融合,A ,B 项目有各自的用户token与自己的交互方式,技术栈一致。之前是用跳链的方式,新开一个页面进行操作,给用户的感官是两个项目较为割裂,目前期望让两个项目看起来像一个整体,减少割裂感。

解决方案

  1. iframe内嵌 + 菜单融合
  2. 微前端融合

iframe内嵌 + 菜单融合

iframe内嵌有两种方式:

第一种是将整个B 项目作为一个页面融入A 项目,这样做的好处是切换页面不会重复请求,session,local等存储便于管理,不会出现样式覆盖。缺点是依旧有一些割裂感,且B 项目是整体作为一个页面,感官上很奇怪。

第二种是将B 项目的多个页面融入A 项目的菜单,整体感官上会是一个整体,但是切换页面的时候容易造成重复请求,白屏等情况,用户体验较差

微前端融合------qiankun

qiankun 是一个由阿里巴巴(蚂蚁金服)团队开源的微前端解决方案。它基于Single-SPA进行二次开发和增强,旨在帮助开发者将单体前端应用改造为由多个独立"微应用"聚合而成的架构。‌‌

如果你是使用umi框架进行开发,我建议使用qiankun,因为umi 提供开箱即用的微前端支持,通过简单的配置即可实现微前端融合

qiankun 使用 Proxy沙箱拦截全局变量,通过重写CSS选择器,添加前缀实现样式隔离,依赖 import-html-entry解析HTML。通过 props 传递和 globalState 进行全局状态管理。基于数据流传递内容

微前端融合------wujie

Wujie 是由‌京东物流技术团队自主研发的微前端框架,用于解决大型前端应用在模块解耦、独立部署、技术栈兼容等方面的挑战。

如果你是使用 vue 进行页面开发,同时期望用尽可能少的改动实现简单的微前端融合,我推荐使用 wujie。

无界使用iframe 作为JS运行沙箱,通过 WebComponent 将渲染内容映射到主应用上,既享受了iframe对JS的绝对隔离,又避免了iframe的UI通信和样式局限性。CSS通过样式作用域和 Shadow-DOM机制,隔离性优于qiankun的Proxy模式。原生支持子应用保活,预加载等功能,开发改动量小。

Wujie 接入

详细代码见:wujie/examples at master · Tencent/wujie · GitHub

主应用改造

main.js 改造

javascript 复制代码
// main.js
import WujieVue from "wujie-vue2";
const isProduction = process.env.NODE_ENV === "production";
const { setupApp, preloadApp, bus } = WujieVue;

bus.$on("click", (msg) => window.alert(msg));

// 在 xxx-sub 路由下子应用将激活路由同步给主应用,主应用跳转对应路由高亮菜单栏
bus.$on("sub-route-change", (name, path) => {
  const mainName = `${name}-sub`;
  const mainPath = `/${name}-sub${path}`;
  const currentName = router.currentRoute.name;
  const currentPath = router.currentRoute.path;
  if (mainName === currentName && mainPath !== currentPath) {
    router.push({ path: mainPath });
  }
});

const degrade = window.localStorage.getItem("degrade") === "true" || !window.Proxy || !window.CustomElementRegistry;
const props = {
  jump: (name) => {
    router.push({ name });
  },
};
/**
 * 大部分业务无需设置 attrs
 * 此处修正 iframe 的 src,是防止github pages csp报错
 * 因为默认是只有 host+port,没有携带路径
 */
const attrs = isProduction ? { src: hostMap("//localhost:8000/") } : {};
/**
 * 配置应用,主要是设置默认配置
 * preloadApp、startApp的配置会基于这个配置做覆盖
 */
setupApp({
  name: "react16",
  url: hostMap("//localhost:7600/"),
  attrs,
  exec: true,
  props,
  fetch: credentialsFetch,
  plugins,
  prefix: { "prefix-dialog": "/dialog", "prefix-location": "/location" },
  degrade,
  ...lifecycles,
});

子应用渲染组件实现

js 复制代码
//Vue2Sub
<template>
  <!--单例模式,name相同则复用一个无界实例,改变url则子应用重新渲染实例到对应路由 -->
  <WujieVue width="100%" height="100%" name="vue2" :url="vue2Url"></WujieVue>
</template>

<script>
import hostMap from "../hostMap";

export default {
  computed: {
    vue2Url() {
      return hostMap("//localhost:7200/") + `#/${this.$route.params.path}`;
    },
  },
  methods: {
    jump(name) {
      this.$router.push({ name });
    },
  },
};
</script>

<style lang="scss" scoped></style>

编写路由!!!

js 复制代码
//router.js
{
    path: "/vue2-sub/:path",
    name: "vue2-sub",
    component: Vue2Sub,
},

总结

wujie 的优势很明显,代码改动量小,无需配置子应用前缀,适合快速接入开发的项目,数据传递主要依赖于事件系统,例如我本来想传递一个全局用户信息给子应用,结果发现数据变化时,不会触发任何内容,并且子应用的 props 也没有更新,所以我自己基于事件传递实现了一套自动化获取token然后登陆的逻辑,实现相关功能。此外wujie的文档较为简单,有些功能函数的具体作用也不是很清晰,只能根据自己去猜(也可能是笔者能力较弱,叠个甲,哈哈哈)

相关推荐
来碗疙瘩汤2 小时前
深入解析 Vue 包:`vue` 究竟导出了什么?
前端
我命由我123452 小时前
React - ref、回调 ref 回调执行次数的问题、createRef 函数、事件处理
前端·javascript·react.js·前端框架·html·html5·js
我命由我123452 小时前
React - 收集表单元素、收集表单元素优化、生命周期(旧)、生命周期(新)
前端·javascript·react.js·前端框架·html·html5·js
SuperEugene2 小时前
Monorepo + pnpm workspace 落地实操:Vue 中后台多项目 / 组件库 / 公共包管理|Vue 工程化篇
前端·javascript·vue.js·pnpm·vite·monorepo
We་ct2 小时前
JSX & ReactElement 核心解析
前端·react.js·面试·架构·前端框架·reactjs·个人开发
白中白121382 小时前
杂七杂八补充系列
开发语言·前端·javascript
Xingxing?!2 小时前
Vue2 微信小程序:页面间传递数组
前端·vue.js·uni-app
肉肉不吃 肉2 小时前
代理服务的原理,及Vite 中具体实现方法
前端·vue.js
前端小D2 小时前
作用域/闭包
前端·javascript