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,以及为啥我们也没选它。

相关推荐
香菜TTT2 小时前
Kafka_深度解析_从架构原理到生产实践
分布式·架构·kafka·linq
陳陈陳3 小时前
🚀 前端流式输出革命:SSE + BFF 架构从零到一实战指南
vue.js·架构·node.js
张永伟营销4 小时前
从SEO到GEO:技术人视角下的生成式引擎优化架构与实践
搜索引擎·ai·架构
小柒儿3364 小时前
AI原生架构:企业IT从“业务数字化”到“AI原生重构”
重构·架构·ai-native
千维百策6665 小时前
云服务性能下降事件分析:高可用架构与可用区疏散实践
架构
EnCi Zheng6 小时前
AI Agent(AI智能体) 记忆管理系统设计 — 从向量库边界到生产级 Memory(记忆) 架构
人工智能·架构
纵有疾風起6 小时前
从OSI到TCP/IP——分层架构的思想根源与模型之争
tcp/ip·计算机网络·架构·osi·408·体系结构·分层
byte_conn6 小时前
高压级联储能通信架构:CAN隔离与光纤中继的选型实战
网络·架构·制造·信息与通信
乐启国际旅行社有限公司8 小时前
微服务高可用实战:Resilience4j熔断降级解决文旅节假日流量雪崩问题
微服务·云原生·架构