Module federation with vite
From Logic Wiki
Contents
Create the apps
bun create vite host --template react-ts bun create vite client-a --template react-ts bun create vite client-b --template react-ts
Add vite-plugin-federations
cd host bun add -d @originjs/vite-plugin-federation cd ../client-a bun add -d @originjs/vite-plugin-federation cd ../client-b bun add -d @originjs/vite-plugin-federation
Remote App (client-a)
client-a/vite.config.ts
import { defineConfig } from "vite"
import react from "@vitejs/plugin-react"
import federation from "@originjs/vite-plugin-federation"
export default defineConfig({
plugins: [
react(),
federation({
name: "client_a",
filename: "remoteEntry.js",
exposes: {
"./Button": "./src/Button.tsx",
},
shared: ["react", "react-dom"],
}),
],
build: {
target: "esnext",
minify: false,
},
server: {
port: 5001,
},
})
client-a/src/Button.tsx
export default function Button() {
return (
<button style={{ padding: 10 }}>
Client A Button
</button>
)
}
client-a/src/main.tsx
import React from "react"
import ReactDOM from "react-dom/client"
function App() {
return <h2>Client A running</h2>
}
ReactDOM.createRoot(document.getElementById("root")!).render(<App />)
Remote App (client-b)
client-b/vite.config.ts
import { defineConfig } from "vite"
import react from "@vitejs/plugin-react"
import federation from "@originjs/vite-plugin-federation"
export default defineConfig({
plugins: [
react(),
federation({
name: "client_b",
filename: "remoteEntry.js",
exposes: {
"./Card": "./src/Card.tsx",
},
shared: ["react", "react-dom"],
}),
],
build: {
target: "esnext",
minify: false,
},
server: {
port: 5002,
},
})
client-b/src/Card.tsx
export default function Card() {
return (
<div style={{ border: "1px solid black", padding: 10 }}>
Client B Card
</div>
)
}
Host App
host/vite.config.ts
import { defineConfig } from "vite"
import react from "@vitejs/plugin-react"
import federation from "@originjs/vite-plugin-federation"
export default defineConfig({
plugins: [
react(),
federation({
name: "host",
remotes: {
client_a: "http://localhost:5001/assets/remoteEntry.js",
client_b: "http://localhost:5002/assets/remoteEntry.js",
},
shared: ["react", "react-dom"],
}),
],
server: {
port: 5000,
},
})
Host React App
host/src/App.tsx
import React, { Suspense } from "react"
const RemoteButton = React.lazy(() => import("client_a/Button"))
const RemoteCard = React.lazy(() => import("client_b/Card"))
export default function App() {
return (
<div>
<h1>Host App</h1>
<Suspense fallback="Loading Button...">
<RemoteButton />
</Suspense>
<Suspense fallback="Loading Card...">
<RemoteCard />
</Suspense>
</div>
)
}
TypeScript Declarations (Important)
host/src/remote.d.ts
declare module "client_a/Button" declare module "client_b/Card"
Without this, TypeScript complains.
Run Everything with Bun
terminal 1
cd client-a bun run dev
terminal 2
cd client-b bun run dev
terminal 3
cd host bun run dev