vite 下使用 Module Federation

Module Federation

Module Federation 的核心是 "打破构建边界,实现模块级的跨应用共享与协同" ,其最佳使用场景需满足以下特征:

  • 应用 / 模块由多团队独立开发维护;
  • 需要复用公共依赖或组件,避免重复打包;
  • 希望简化模块更新流程(免 npm 发布);
  • 需实现微前端、跨技术栈协作或模块级灰度发布。
    注意: 每个应用都可以在 Federation 中暴露 或者加载 远程可共享模块

如何使用 vite 搭建 MF

项目 github 参考地址: github.com/kejuqu/febe...

创建两个应用 vite-reactvite-react-provider

  • vite-react-provider 暴露 Button 组件
  • vite-react 使用 vite-react-provider 应用暴露的 Button 组件

vite-react-provider 应用

js 复制代码
// vite.config.ts
import { defineConfig, type PluginOption } from "vite";
import react from "@vitejs/plugin-react";
import { federation } from "@module-federation/vite";

// https://vite.dev/config/
export default defineConfig({
  server: {
    port: 3006,
  },
  plugins: [
    react({
      babel: {
        plugins: [["babel-plugin-react-compiler"]],
      },
    }),
    federation({
      name: "remote",
      filename: "remoteEntry.js",
      // exposes 暴露 组件或者使用的工具函数
      exposes: {
        "./c-button": "./src/components/button.tsx",
      },
      shared: ["react", "react-dom"],
    }) as PluginOption[],
  ],
});

// src/components/button.tsx
export default function Button(props: React.ComponentProps<"button">) {
  return <button {...props}>button from remote</button>;
}

vite-react 使用 React.Lazy + dynamic import 加载远程模块

js 复制代码
// vite.config.ts
import { defineConfig } from "vite";
import { federation } from "@module-federation/vite";
import react from "@vitejs/plugin-react";

// https://vite.dev/config/
export default defineConfig({
  server: {
    port: 3005,
  },
  plugins: [
    react({
      babel: {
        plugins: [["babel-plugin-react-compiler"]],
      },
    }),
    federation({
      name: "customer",
      filename: "vite-react.js",
      // // exposes 暴露 组件或者使用的工具函数
      // exposes: {
      //   "./utils": "./src/utils.tsx",
      // },
      remotes: {
        remote: {
          type: "module",
          name: "remote",
          entry: "http://localhost:3006/remoteEntry.js",
          entryGlobalName: "remote",
          shareScope: "default",
        },
      },
      shared: ["react", "react-dom"],
    }),
  ],
});


// src/App.tsx
import React from "react";
import "./App.css";

function App() {
  const RemoteBtn = React.lazy(() => import("remote/c-button"));

  return (
    <>
      <React.Suspense fallback={<div>loading...</div>}>
        <RemoteBtn onClick={() => alert("clicked")} />
      </React.Suspense>
    </>
  );
}

export default App;

效果图

相关推荐
IT_陈寒9 分钟前
Python装饰器把我坑惨了,原来这样用才不掉链子
前端·人工智能·后端
程序员爱钓鱼28 分钟前
Rust Associated Type关联类型详解:为Trait定义内部类型
前端·后端·rust
zh_xuan1 小时前
个人主页左侧菜单支持分组,以及菜单显示和隐藏
前端·javascript·css
Emily156853598704 小时前
Emerson 1C31129G03 Analog Input Module
java·开发语言·前端·plc·emerson·1c31129g03·input module
To_OC9 小时前
面试被问了三回三栏布局,这次我终于把 BFC 那层窗户纸捅破了
前端·css·面试
To_OC10 小时前
啃完 TS 工具类型我发现:Pick 和 Omit 原来就是一层窗户纸
前端·面试·typescript
风月说与山鬼11 小时前
三、大括号语法
前端·react.js
kyriewen11 小时前
我把最常踩的8个CORS跨域报错整理了一遍——第8个去年还不存在
前端·javascript
Csvn12 小时前
🕰️ 闭包 + setTimeout 的 5 个经典陷阱:为什么定时器看到的永远不是最新的值?
前端