I am trying to module federation with vite-react. I did all configurations in the vite.config.js file in both host and remote. But when i am accessing the imported files of remote in the host it is showing blank screen
I am trying to set up module federation with Vite using @originjs/vite-plugin-federation. I have a remote app exposing components and a host app importing them. However, when I try to access http://localhost:5173/assets/remoteEntry.js, it returns an HTML page instead of JavaScript.
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'
import federation from '@originjs/vite-plugin-federation';
export default defineConfig({
plugins: [
react(),
federation({
name: 'remote_app',
filename: 'remoteEntry.js',
exposes: {
'./Button': './src/button.jsx',
'./Header': './src/components/Header.jsx'
},
shared: ["react", "react-dom", "jotai"],
})
],
build: {
modulePreload: false,
target: 'esnext',
minify: false,
cssCodeSplit: false
},
});
This is remote config. Trying share Button and Header
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react-swc';
import federation from '@originjs/vite-plugin-federation';
export default defineConfig({
plugins: [
react(),
federation({
name: 'host_app',
remotes: {
remote_app: 'http://localhost:5173/assets/remoteEntry.js'
},
shared: ["react", "react-dom"]
})
],
build: {
modulePreload: false,
target: 'esnext',
minify: false,
cssCodeSplit: false
}
});
This is host config
Loading components in host App
const RemoteButton = React.lazy(() => import('remote_app/Button'))
const Header = React.lazy(() => import('remote_app/Header'))
<Suspense fallback={<LoadingView />}>
<Route exact path='/button' element={<RemoteButton />} />
<Route exact path='/header' element={<Header />} />
</Suspense>
versions:
“@vitejs/plugin-react-swc”: “^3.5.0”,
“@originjs/vite-plugin-federation”: “^1.3.9”,
“react-router-dom”: “^7.2.0”,
When i navigated to /button route or /header route it is a blank screen.
For debugging i tried to import with promise function in useEffect of App.jsx
useEffect(() => {
import("remote_app/Button")
.then((module) => {
console.log("RemoteButton loaded:", module);
})
.catch((error) => {
console.error("Failed to load RemoteButton:", error);
});
}, []);
Error i the browser console:
Uncaught TypeError: Failed to fetch dynamically imported module: http://localhost:5173/assets/remoteEntry.js
in the browser console following error is shown
Network tab response for http://localhost:5173/assets/remoteEntry.js:
Status: 200
Response Body: Instead of JS, it returns the default Vite HTML page
<!doctype html>
<html lang="en">
<head>
<script type="module">import { injectIntoGlobalHook } from "/@react-refresh";
injectIntoGlobalHook(window);
window.$RefreshReg$ = () => {};
window.$RefreshSig$ = () => (type) => type;</script>
<script type="module" src="/@vite/client"></script>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>
What I Have Tried:
Checked the remoteEntry.js URL: It loads an HTML page instead of a JS module.
Manually importing in useEffect:
useEffect(() => {
import("remote_app/Button")
.then((module) => {
console.log("RemoteButton loaded:", module);
})
.catch((error) => {
console.error("Failed to load RemoteButton:", error);
});
}, []);
Expected Outcome:
http://localhost:5173/assets/remoteEntry.js should return the federated module, not an HTML page.
Remote components should load successfully in the host app.
Why is remoteEntry.js not being generated properly, and how do I fix this?
Both host and remote vite+react applications.
I tried in many ways but i can’t understand what is the mistake.