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

相关推荐
程序员侠客行2 小时前
Mybatis二级缓存实现详解
java·数据库·后端·架构·mybatis
AutoMQ2 小时前
🎉 庆祝 AutoMQ 在 GitHub 上突破 9k Stars!
架构
GISer_Jing3 小时前
AI编程革命:Trae如何重塑前端开发
前端·前端框架·aigc·ai编程
Xの哲學3 小时前
Linux CFS 调度器深度解析
linux·服务器·算法·架构·边缘计算
阳光普照世界和平4 小时前
2025年智能体架构与主流技术深度研究报告:从生成式AI迈向自主执行层
人工智能·架构
码头工人5 小时前
【架构师系列】风控场景下超高并发频次计算服务的设计与实践
java·架构·风控·反爬
村口曹大爷6 小时前
【深度】OpenAI 推理架构演进:GPT-5.2(Internal版)性能实测与开发者接入路径分析
gpt·ai·chatgpt·架构·gpt5.2
光影少年7 小时前
AI前端开发需要会哪些及未来发展?
前端·人工智能·前端框架
踏浪无痕7 小时前
从 node-exporter 学如何写出可复用的监控指标
运维·后端·架构
C_心欲无痕7 小时前
react - useTransition标记低优先级更新
前端·react.js·前端框架