Skip to content
页面大纲

外部系统集成





外部系统集成




外部系统集成到目前的微前端框架下,有两种方式:

  • iframe 集成。传统的集成方式。这种情况可以创建一个子应用,负责管理 iframe, 比如维护会话信息、通信等等
  • 微前端子应用集成。 基座提供了很多能力,但是对于子应用来说都是可选的。对于外部系统而言,仅需少量改造, 就能集成进来。


WARNING

基座接管了导航菜单的渲染,因此不管是哪种集成方式, 外部子应用都需要

  • 隐藏掉自身的菜单、导航组件框架
  • 风格统一


怎么选择?


iframe?:

  • 优势

    • iframe 是浏览器原生支持的‘硬隔离’方案,可以完美隔离样式、Javascript
    • 兼容性好
  • 劣势

    • 性能较差、用户体验也稍差。每次子应用进入都是一次浏览器上下文重建、资源重新加载的过程。
    • URL 不同步。需要额外的基座/子应用通信来保持 url 和菜单的联动。
    • 弹框类的功能无法应用到整个大应用中,只能在对应的 iframe 窗口内展示。
    • 状态、会话、样式无法共享。成也是隔离,败也是隔离,iframe 最大的问题也在于他的隔离性无法被突破。 需要额外的通信、或其他复杂手段才能做到。


微前端子应用集成?:

  • 优势
    • 解决了 iframe 的一些劣势,性能和体验都不错。同时也能保证应用的隔离性。
    • 支持共享状态、样式、会话、依赖等等
  • 劣势
    • 基座和子应用在同一 DOM 树下渲染,需要避免子应用污染基座, 有一些适配工作。
    • 子应用静态资源拉取需要支持跨域

  • 不适用的场景
    • 本身就是巨石应用,系统比较庞大。
    • 应用服务于多个系统,很难只针对我们特定修改。只能是我们主动对接的场景




1. iframe 集成


创建子应用,以 Vue 3 为例子:

创建路由:

import { createRouter, createWebHashHistory } from 'vue-router';
import ExternalIntergration from './ExternalIntergration';

const router = createRouter({
  // 使用 hash
  history: createWebHashHistory(),
  routes: [
    {
      // 匹配所有路由
      path: '/:any*',
      component: ExternalIntergration,
    },
  ],
});


iframe 包裹:

<template>
  <iframe :src="target"></iframe>
</template>

<script>
  import { defineComponent, computed } from 'vue';
  import { useRoute } from 'vue-router';

  export default defineComponent(() => {
    const route = useRoute();
    const target = computed(() => {
      // 封装外部系统链接,可以在这里传入路由、鉴权信息
      return `https://wakeadmin.wakefe.top?token=${token}#${route.fullPath}`;
    });

    return { target };
  });
</script>

上述的方案,可以用于简单的集成场景。它有以下确定:

  • 采用了基座到子应用路由的单向联动,子应用内部路由跳转不会响应到基座
  • 直接设置 iframe src 会导致强刷,性能和体验差。


因此需要基座需要额外的通信来保持菜单和路由的联动:



挂载应用:



import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import bay from '@wakeadmin/bay';

let app;

bay.createMicroApp({
  async mount(props) {
    app = createApp(App);
    app.use(router);
    app.mount(props.container ? props.container.querySelector('#app') : '#app');
  },

  async unmount(props) {
    app.unmount();
  },
});




最后参照 部署 进行部署就可以了。





2. 最小化改造集成到基座



调整应用挂载方式:

import { createApp } from 'vue';
import App from './App.vue';
import router from './router';

const APP_NAME = 'APP_NAME'; // 必须唯一
let app;

async function bootstrap() {
  console.log('bootstraped');
}

async function mount(props) {
  app = createApp(App);
  app.use(router);
  app.mount(props.container ? props.container.querySelector('#app') : '#app');
}

async function unmount(props) {
  app.unmount();
}

async function update(props) {
  console.log('update props', props);
}

window[APP_NAME] = {
  bootstrap,
  mount,
  unmount,
  update,
};

// 不在微前端框架下, 直接渲染
if (typeof window.__MAPP_BAY__ === 'undefined') {
  mount();
}


如果要本地调试,还要配置 webpack:

// 以 vue-cli 为例子:
const { defineConfig } = require('@vue/cli-service');

// 开发服务器端口号
const port = 9999;
module.exports = defineConfig({
  // 以下配置只用于本地开发
  // 保证基座能够正常加载
  publicPath: process.env.NODE_ENV === 'production' ? '<应用的部署路径、或者 CDN 地址>' : `http://localhost:${port}/`,
  devServer: {
    port,
    https: true,
    // 支持跨域
    headers: { 'Access-Control-Allow-Origin': '*' },
  },
});


最后再将子应用信息注册到基座即可





集成到外部系统


子应用集成到第三方外部系统,基本上也有两种方式:

  • 子应用独立集成到外部系统。适用于子应用本身是一个比较独立的系统,对基座及基座背后的服务体系没有深度的依赖;或者子应用本身就要求支持独立售卖、外部系统集成的场景。比如 CDP
  • 将微前端基座 + 子应用集成到外部系统。和上面相反,比如运营中心、营销中心这些应用深度耦合了惟客云的服务体系。

子应用独立兼容多种集成方式

有些应用可能需要同时适配多种集成方式,比如 CDP 既可以集成到惟客云,也可以和惟数平台集成。对于这种应用不建议过多耦合基座,避免给程序兼容和迁移带来不必要的复杂度

条件判断是否在微前端基座下:

if (window.__MAPP_BAY__) {
  // 微前端基座下
  // 比如隐藏导航栏、侧边栏
  // 按基座要求的方式挂载应用
} else {
  // 其他集成模式
}



微前端基座+子应用作为整体集成

通常可以使用 iframe 的形式集成,如果需要隐藏菜单带上 __mapp_standalone__=true 参数, 比如:


<iframe src="https://myhost/path/to?__mapp_standalone__=true#/hash-path" />




扩展阅读

客户经营,找惟客