vite icon indicating copy to clipboard operation
vite copied to clipboard

[Bug]: Failed to locate remote. #RUNTIME-004

Open dongnaebi opened this issue 6 months ago • 11 comments

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

dongnaebi avatar Jun 25 '25 12:06 dongnaebi

Hi @dongnaebi thanks for the feedback, unfortunately without a reproduction repository this hard to find the problem 😔

gioboa avatar Jun 25 '25 14:06 gioboa

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:

Image

Achder avatar Jul 14 '25 11:07 Achder

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",
                }
          
      ]

Achder avatar Jul 14 '25 12:07 Achder

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)

Achder avatar Jul 18 '25 09:07 Achder

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?

Achder avatar Jul 18 '25 10:07 Achder

Thanks for sharing your findings 👏 If you want you can try to drop a PR for this, more than happy to review it.

gioboa avatar Jul 18 '25 11:07 gioboa

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.

ymor avatar Aug 06 '25 14:08 ymor

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.

alanjhonnes avatar Aug 11 '25 21:08 alanjhonnes

@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(), ], })

`

somnathnavale avatar Sep 14 '25 12:09 somnathnavale

@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.

Achder avatar Sep 16 '25 07:09 Achder

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.

marcelkalveram avatar Oct 28 '25 19:10 marcelkalveram