VITE + 邦联模块(module federation)实现

好了,来填坑了,在基于VITE手动搭建Single-spa框架一文中,曾说过,确认前后端均采用微服务+单点登录方案后,就去筛选前端微服务方案了么。那么,第二个前端微服务方案,如期而至了。

前端微服务方案,当时用的比较多的,主要是有以下几个方案:

  1. google 旗下的 single-spa.
  2. 阿里旗下,基于 single-spa 的 Qiankun.
  3. 京东基于 webComponent 原生组件的 Micro-app.
  4. module federation, webpack5 原生支持的技术方案.
  5. 字节跳动推出的 garfish.

当然,也还有其他前端微服务框架和方案,如:Luigi, open components, piral 等等,不一而足。只是前述列表,才是我做了预研和 demo 的方案,本想一个一个讲一讲各个方案的优缺点,但我仅仅前浅显的做了demo,没有深入研究,就请参考除了 Qiankun, 这些微前端框架或许更适合你「建议收藏」这篇文章吧。调研时,还没用过 vite,所以直接使用的 webpack5,现在 vite 性能上已经超出了 webpack,所以,就使用 vite 来完成这个 demo 吧。

基座(base)

使用 手动搭建VITE + REACT 一文中搭建的 React 项目作为基础项目,作为 base 项目。项目结构如下图:

关键配置如下:

typescript 复制代码
....原有配置
+ import federation from '@originjs/vite-plugin-federation'
export default defineConfig({
    plugins:[
        ... 原有配置
        federation({
            name:'host',
            remotes:{
                // 远程模块引入 引入格式 name:入口地址,远程组件需要打包部署后,运行在一个实体服务器内,或者使用开发服务器
                'remote':'localhost:30001/remote.js'
            },
            shared:['react','react-dom'] // 共享依赖
        })
    ]
    ... 原有配置
})

子项目(remote, 向 base 提供组件)

同上,项目同样为 react 项目,项目结构相同,只是新增了 components 目录,其中存放了需要向外暴露的公共组件,关键配置如下:

typescript 复制代码
....原有配置
+ import federation from '@originjs/vite-plugin-federation'
export default defineConfig({
    plugins:[
        ... 原有配置
        federation({
            name:'remote', // 名称,唯一标识
            filename:'remote.js', // 入口文件名称,可以不填,不填则是默认的 remoteEntry.js
            exposs:{
                // 暴露的模块路径及访问别名 访问别名:模块路径
                './Button': './src/components/button/index.tsx'
            },
            shared:['react','react-dom'] // 共享依赖
        })
    ],
    build:{
        ... 原有配置
        target:'esnext' // 必须使用 ES 模块
    },
    server:{
        ... 原有配置
        headers: {'Access-Control-Allow-Origin':'*' // 允许跨域访问
    }
    ... 原有配置
})

在base项目中引用远程组件

typescript 复制代码
import React, { Suspense, lazy } from 'react'

const RemoteButton = lazy(() => import('remote/Button')) // 引入远程组件,remote 是在 vite.config.ts 中配置的name
const App: React.FC = () => {
  console.log('App')
  return (
    <div>
      <Suspense fallback={<div>loading</div>}>
        <RemoteButton />
      </Suspense>
    </div>
  )
}

export default App

注意事项

如果使用ts,eslint会报类型错误,需要去定义类型。

typescript 复制代码
// global.d.ts,可以放在项目根目录下
declare module 'remote-app/Button' {
  const component: any
  export default component
}

可使用场景

  1. 调研时,使用的是webpack5,原生支持 federation。
  2. 使用 vite 时,需要使用 vite-plugin-federation 插件来实现。
  3. 使用时,需要注意版本,各版本不兼容的情况下,功能会缺失。
  4. 跨框架使用,要注意各框架的的区别,各模块的依赖,需要在 shared 中配置,否则依赖框架的功能会失效。
  5. 各远程项目独立运行时,建议打包后,放在web容器中部署运行,使用 vite 的 server 模块时,会碰到无法加载到入口 (remoteEntry.js) 找不到的尴尬情况。(目前我还没解决,主要是不打包的情况下,remoteEntry.js这个文件不会生成)。
  6. 该方案比较适合的场景,是独立的纯逻辑组件|纯UI组件复用,且颗粒度较小。有副作用(例如影响提供远程组件的项目里的数据,对提供远程组件的项目的业务逻辑有影响)的话,需要谨慎使用,除非各个项目组协调一致。

结语

由于当时公司各个项目的后台管理端采用的框架 (vue2,react,angular,backbone) 各不相同,且版本也五花八门没有统一,使用邦联模块的改造难度和工作量远超预期,所以当时我们并未选用该方案。好了,下期,我们讲讲阿里的Qiankun,以及为啥我们也没选它。

相关推荐
junjun.chen06063 小时前
【在qiankun模式下el-dropdown点击,浏览器报Failed to execute ‘getComputedStyle‘ on ‘Window‘: parameter 1 is not o
前端·javascript·前端框架
MZWeiei5 小时前
Spark SQL 运行架构详解(专业解释+番茄炒蛋例子解读)
大数据·分布式·sql·架构·spark
#金毛5 小时前
一、HAL库的设计理念详解:从架构到实践
stm32·嵌入式硬件·架构
是麟渊5 小时前
【大模型面试每日一题】Day 17:解释MoE(Mixture of Experts)架构如何实现模型稀疏性,并分析其训练难点
人工智能·自然语言处理·面试·职场和发展·架构
好吃的肘子5 小时前
MongoDB 高可用复制集架构
数据库·mongodb·架构
TsingtaoAI5 小时前
医疗系统开发架构和技术路线建议-湖南某三甲医院
架构·医疗ai系统·医疗信息化·医疗系统架构·医疗ai机构
敲代码的 蜡笔小新6 小时前
【行为型之命令模式】游戏开发实战——Unity可撤销系统与高级输入管理的架构秘钥
unity·设计模式·架构·命令模式
码上飞扬7 小时前
MongoDB数据库深度解析:架构、特性与应用场景
数据库·mongodb·架构
刺客-Andy7 小时前
React 第四十一节Router 中 useActionData 使用方法案例以及注意事项
前端·react.js·前端框架
九章云极AladdinEdu8 小时前
GPU SIMT架构的极限压榨:PTX汇编指令级并行优化实践
汇编·人工智能·pytorch·python·深度学习·架构·gpu算力