[Bug]: Failed to locate remote. #RUNTIME-004
Describe the bug
When I run npm run dev, everything works fine, but after building and running preview, I get the following error:
Uncaught (in promise) Error: [ Federation Runtime ]: Failed to locate remote. #RUNTIME-004
args: {"hostName":"host","requestId":"remote/App"}
Here is my configuration:
// host
export default defineConfig({
plugins: [
VueRouter({
exclude: ['**/components/**', '**/composables/**'],
extensions: ['.vue', '.tsx'],
}),
vue(),
vueJsx(),
tailwindcss(),
vueDevTools(),
federation({
name: 'host',
remotes: {
remote: {
type: 'module',
name: 'remote',
entry: '/legacy-app/remoteEntry.js',
entryGlobalName: 'remote',
shareScope: 'default',
},
},
}),
topLevelAwait(),
],
build: {
target: 'chrome75',
},
resolve: {
alias: {
'~': fileURLToPath(new URL('./src', import.meta.url)),
'@': fileURLToPath(new URL('./src', import.meta.url)),
},
},
server: {
proxy: {
'/legacy-app': {
target: 'http://localhost:9888/',
changeOrigin: true,
rewrite(path) {
return path.replace('/legacy-app', '')
},
},
},
},
})
federation({
name: 'remote',
filename: 'remoteEntry.js',
exposes: {
'./App': './src/main.js'
}
})
what's wrong with me?
I found a similar issue: https://github.com/module-federation/core/issues/3710
Version
v6.2.4
Reproduction
maybe later
Relevant log output
Validations
- [x] Read the docs.
- [x] Read the common issues list.
- [x] Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
- [x] The provided reproduction is a minimal reproducible example of the bug.
Hi @dongnaebi thanks for the feedback, unfortunately without a reproduction repository this hard to find the problem 😔
I have a similar issue. My host config:
federation({
name: "host",
filename: "remoteEntry.js",
remotes: {
chat: 'chat@http://localhost:5174/mf-manifest.json',
},
shared: {
react: {
singleton: true
},
"react-dom": {
singleton: true
},
'react/jsx-runtime': {
singleton: true
},
'react-dom/client': {
singleton: true
},
},
}),
The remote is served through vite preview --port 5174
The manifest can be loaded at the URL.
My workaround:
What I found helps is changing the config while the dev-server is running.
The page will hot-reload and work afterwards.
For example if I start with the config above I get the mentioned error.
But if I keep the dev server of the host running and change the filename to remoteEntry-2.js the page reloads and loads the component correctly.
If I stop the dev-server and restart it, the page is broken again. If I now change the filename to remoteEntry-3.js while the dev server keeps running it's working again.
I don't know how to create a reproduction of this. I'd love to but I can't :(
Also while investigating I found that leaving the filename undefined results in "remoteEntry-[hash]". But the "hash" is never resolved for me. See this exerpt from the devtools:
I found out that usedRemotes in /.__mf__temp/host/localSharedImportMap.jsis empty when I first start the app.
After a hot-reload it is set correctly:
const usedRemotes = [
{
entryGlobalName: "http://localhost:5174/mf-manifest.json",
name: "chat",
type: "var",
entry: "http://localhost:5174/mf-manifest.json",
shareScope: "default",
}
]
I kind of finally found a working setup.
The issue seems to be a timing issue.
I now re-initialize the federation host using import { init } from '@module-federation/runtime'
I kept the plugin initialization in the vite.config.ts but I moved the plugin options to a separate federation.config.ts:
I created a new file federation-init.ts in my src folder:
import { init } from '@module-federation/runtime'
import { federationConfig } from '../federation.config'
// Initialize Federation runtime manually
// @ts-expect-error <-- this is because of the remotes array
init(federationConfig)
I have somewhat fixed this now for me. Something goes wrong during initialization. The remotes are not loaded. I'm now re-initializing the federation host manually. Since I'm initializing the plugin twice now, I created a factory function to generate the shared config data.
Here's the file for the shared config. Note: The structure is arbitrary. The vite-plugin and the manual init function from @module-federation/runtime expect different objects. So I just save this for usage later.
export function federationConfigFactory (mode: string) {
return {
name: 'host',
remote: {
name: 'chat',
entry: mode === 'development'
? 'http://localhost:5174/mf-manifest.json'
: '/my/prod/path/remoteEntry.js',
}
}
}
I created a federation-init.ts that I import as the first thing in my code.
The federation-init.ts itself:
import { init } from '@module-federation/runtime'
import { federationConfigFactory } from '../federation.config'
// Initialize Federation runtime manually
// @ts-expect-error
const config = federationConfigFactory(import.meta.env?.MODE)
init({
name: config.name,
remotes: [config.remote]
})
And here the import im my index.ts:
import './federation-init' <-- see here
import React from 'react'
import { createRoot } from 'react-dom/client'
import { Application } from './Application'
const root = createRoot(document.getElementById('root'))
root.render(<Application />)
if (import.meta.hot) import.meta.hot.accept()
My vite configs federation plugin now also uses the factory data:
federation({
name: federationConfig.name,
remotes: {
[federationConfig.remote.name]: federationConfig.remote.entry
},
shared: {
react: {
singleton: true
},
'react-dom': {
singleton: true
},
'react/jsx-runtime': {
singleton: true
},
'react-dom/client': {
singleton: true
},
}
}),
I kept the shared entry in the plugin config because I can't set the singletonoption in the manual init() function.
With this the federation host is initialized correctly and I can use it.
Maybe that helps when with the analyses a bit?
Thanks for sharing your findings 👏 If you want you can try to drop a PR for this, more than happy to review it.
Just ran into this issue myself and just wanted to add that init is now deprecated as per https://module-federation.io/guide/basic/runtime/runtime-api.html#pure-runtimenot-use-build-plugin
Using registerRemotes solved it for me.
I've ran into this problem and when I configure the remotes in the plugin's configuration I notice that they are only included in the mf-manifest.json file and in the default ModuleFederation runtime instance if there is an import('remoteName') somewhere in the code, so it is probably getting tree-shaken if you are just using loadRemote('remoteName').
Using registerRemotes seems to work to patch up the built MF instance, but I'm not sure if it has other implications.
@Achder , I am getting the same issue and, I am using the vite 7.1.2, i tried to go through all the points you have mentioned but not able to understand i am attaching the my remote and host app configurations below, could you please help me with solving the issue, i am trying out the microfrontend for the first time, Thanks,
Host App vite configs ` import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import {federation} from '@module-federation/vite'
export default defineConfig({ server: { port: 5000, cors: true }, build: { modulePreload: false, target: "esnext", minify: false, cssCodeSplit: false, }, plugins: [ federation({ name: 'hostApp', filename: "remoteEntry.js", remotes: { remote: { name: "remoteApp", entry: "http://localhost:5001/remoteEntry.js", }, }, shared: { react: { singleton: true }, "react-dom": { singleton: true } }, manifest: true }), react(), ], }) `
Remote App Configs ` import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import {federation} from '@module-federation/vite'
export default defineConfig({ server: { port: 5001, cors: true }, build: { modulePreload: false, target: "esnext", minify: false, cssCodeSplit: false, }, plugins: [ federation({ name: 'remoteApp', filename: 'remoteEntry.js', exposes: { './HelloRemote': './src/HelloRemote.jsx', }, shared: { react: { singleton: true }, "react-dom": { singleton: true } }, }), react(), ], })
`
@Achder , I am getting the same issue and, I am using the vite 7.1.2, i tried to go through all the points you have mentioned but not able to understand i am attaching the my remote and host app configurations below, could you please help me with solving the issue, i am trying out the microfrontend for the first time, Thanks,
Host App vite configs ` import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import {federation} from '@module-federation/vite'
export default defineConfig({ server: { port: 5000, cors: true }, build: { modulePreload: false, target: "esnext", minify: false, cssCodeSplit: false, }, plugins: [ federation({ name: 'hostApp', filename: "remoteEntry.js", remotes: { remote: { name: "remoteApp", entry: "http://localhost:5001/remoteEntry.js", }, }, shared: { react: { singleton: true }, "react-dom": { singleton: true } }, manifest: true }), react(), ], }) `
Remote App Configs ` import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import {federation} from '@module-federation/vite'
export default defineConfig({ server: { port: 5001, cors: true }, build: { modulePreload: false, target: "esnext", minify: false, cssCodeSplit: false, }, plugins: [ federation({ name: 'remoteApp', filename: 'remoteEntry.js', exposes: { './HelloRemote': './src/HelloRemote.jsx', }, shared: { react: { singleton: true }, "react-dom": { singleton: true } }, }), react(), ], })
`
Try running this in your code as early as possible:
import { registerRemotes } from '@module-federation/enhanced/runtime';
registerRemotes([
{
name: "remoteApp",
entry: "http://localhost:5001/remoteEntry.js",
}
]);
You need to make sure this runs before you are trying to import on of the remote components.
In my case, the Sentry plugin @sentry/vite-plugin was breaking the build. Took me a few hours to debug, but seems like it's a known issue with Module Federation that got fixed with the latest release (4.6.0). Alternatively, it seems you can set Sentry's telemetry to false. Hope that helps anyone running into the same issue.