微前端场景下的子应用联调方案探索实践

lxf2023-03-16 17:47:01

前言

现在有很多的中大型项目都用上了微前端方案,有的用qiankun、有的用 iframe、有的用模块联邦,不管用什么实现,切合自身需求场景的才是好的实现。本文讲下,在作者工作的背景下,在公司微前端的架构下,如何高效地进行前后端联调。

痛点

前端开发人员是期望能够在不启动基座应用的条件下进行子应用的开发联调,因为他们往往只需要关注他们负责的子应用、子模块,一般不需要去关注基座应用。

有些项目可能是因为基座技术债积累太多而上了微前端,通过微前端的隔离进行代码的逐步迁移,基座应用可能十分复杂,代码量超过了五六十万行,本地启动基座应用,跑起来耗时久,甚至导致电脑卡顿,开发效率很低。

本地同时开启基座应用和子应用,操作起来也比较麻烦,同时开启多个项目也是会消耗机器性能的。

方案

基于以上痛点和期望不启动基座应用就能进行子应用开发联调的需求,我提供了两种方案:

  1. 代理线上环境静态资源
  2. 模拟登录

方案1-代理线上环境静态资源

前置条件

我们需要提前安装好两个工具:

  1. 谷歌插件SwitchyOmega:github.com/FelisCatus/…
  2. Whistle:github.com/avwo/whistl…

SwitchOmega用来做浏览器代理,Whistle用来拦截修改静态资源请求

具体步骤

我们拿到线上环境之后进行登录访问,可以从控制台去分析环境会去加载哪些静态资源,分析子应用静态资源请求的特征。这里做一个场景假设,假设我们的子应用静态资源都是形如https://dalao.com/submod/daidaiwo.js的、带submod前缀的静态资源,

本地pnpm run dev启动子应用项目,我们的思路就是要把线上环境的/submod/xxx请求修改为请求本地的静态资源。

我们接着启动whistle:w2 start

微前端场景下的子应用联调方案探索实践

按照w2提示,访问http://127.0.0.1:8899,可以看到w2的配置页面,然后输入下面的匹配规则

wss://dalao.com/ws wss://localhost:8081/ws
^https://dalao.com/submod/*** https://localhost:8082/$1

记得修改完规则后进行手动保存,不然不生效。

接着通过谷歌插件SwitchyOmega配置代理服务器为127.0.0.1:8899,记得改完后保存,然后切换为你刚刚配置的情景模式

上述配置都完成之后就可以刷新线上环境的页面,可以看到请求到了本地的内容,websocket也是101状态,我们尝试对子应用的代码进行修改,发现代码热更新可以正常使用。

方案2-模拟登录

模拟登录方案需要你梳理基座应用的登录流程,把这一套流程用代码编写,在子应用中模拟登录一遍,拿到必要的cookie和token等东西,保存起来,每次接口请求时携带它们。

当然也有方法不用去拷贝复写一份模拟登录代码。

我们登录线上环境之后,查看接口的调用细节,把cookie和token等必要的认证信息拷贝下来,粘贴到你的vite配置或webpack配置中,配置示例如下:

vite.config.ts配置示例:

proxy: {
    '/api': {
        target: 'https://1.1.1.1:4450',
        changeOrigin: true,
        secure: false,
        headers: {
            Cookie: 'xxx',
            XxToken: 'xxxx',
        },
    },
}

webpack配置示例:

proxy: [{
    context: '/api',
    router: () => 'https://1.1.1.1:4450',
    changeOrigin: true,
    secure: false,
    onProxyReq(proxyReq) {
         proxyReq.setHeader('Cookie', 'xxx');
         proxyReq.setHeader('XxToken', 'xxxx');
    },
}]

这样子就能实现接口的代理了。

两种方案的对比

第一种方案我是比较推荐的。

  1. 因为第二种方案存在认证过期的问题,只要认证过期了,你就得重新配置一遍
  2. 第二种方案需要经常改动配置,因为cookie是会一直变化的
  3. 子应用有可能是依赖基座应用注入的东西的,比如一些全局数据,一些方法函数,第二种方案需要对这些基座注入的东西进行mock