Module Federation
Module Federation 的核心是 "打破构建边界,实现模块级的跨应用共享与协同" ,其最佳使用场景需满足以下特征:
- 应用 / 模块由多团队独立开发维护;
- 需要复用公共依赖或组件,避免重复打包;
- 希望简化模块更新流程(免 npm 发布);
- 需实现微前端、跨技术栈协作或模块级灰度发布。
注意: 每个应用都可以在 Federation 中暴露 或者加载 远程可共享模块
如何使用 vite 搭建 MF
项目 github 参考地址: github.com/kejuqu/febe...
创建两个应用 vite-react 和 vite-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;
效果图
