Justin Slijkhuis
Justin Slijkhuis

Reputation: 21

Protocol http is not support by the default ESM loader

My goal is to import components from website A in website B using vite-plugin-federation so I can use the same components in both websites. For technical details:

I have a single component exposed in website A. When I navigate to 'http://localhost:5173/dist/assets/remoteEntry.js', then I can see the code for the component there. In website B, when I use fetch('http://localhost:5173/dist/assets/remoteEntry.js'), then it also shows this code. So website B is able to see the code of the exposed website A component.

Yet when I use the code below in my vite.config.ts of website B, then it keeps giving me the error below the code snippet. Some people suggested it was caused by Windows, but moving both websites to Linux Docker containers did not help. Others suggested an outdated Node version, but I am already using the latest version of Node. Downgrading to a different version also does not help.

Host Vite plugin configuration:

plugins: [qwikCity(), qwikVite(), tsconfigPaths(), federation({
    name: "b",
    remotes: {
        a: 'http://localhost:5173/dist/assets/remoteEntry.js'
    },
})],

Remote Vite plugin configuration:

plugins: [qwikCity(), qwikVite(), tsconfigPaths(), federation({
    name: "a",
    filename: "remoteEntry.js",
    exposes: {
        "./Heading": "./src/components/heading/heading.tsx",
    },
})],

Error:

Error when evaluating SSR module /app/cms/src/routes/index.tsx: failed to import "http://localhost:5173/dist/assets/remoteEntry.js"
Error [ERR_UNSUPPORTED_ESM_URL_SCHEME]: Only URLs with a scheme in: file and data are supported by the default ESM loader. Received protocol 'http:'

After doing more research, I found that the import function of ESM does not support importing HTTP or HTTPS URLs. So vite-plugin-federation isn't able to import the remoteEntry.js page. Anyone know what to do in this situation?

Before anyone asks: I am very positive that website B can reach remoteEntry.js of website A, even with my Docker setup.

As specified before:

Here is the command that I run to start Qwik website: "vite --open --mode ssr --host" and here is the full error:

[vite] Error when evaluating SSR module /app/cms/src/routes/index.tsx: failed to import "http://localhost:5173/dist/assets/remoteEntry.js"
|- Error [ERR_UNSUPPORTED_ESM_URL_SCHEME]: Only URLs with a scheme in: file and data are supported by the default ESM loader. Received protocol 'http:'
at getSource (node:internal/modules/esm/load:53:11)
at defaultLoad (node:internal/modules/esm/load:116:40)
at ModuleLoader.load (node:internal/modules/esm/loader:670:12)
at ModuleLoader.loadAndTranslate (node:internal/modules/esm/loader:483:43)
at #createModuleJob (node:internal/modules/esm/loader:507:36)
at #getJobFromResolveResult (node:internal/modules/esm/loader:275:34)
at ModuleLoader.getModuleJobForImport (node:internal/modules/esm/loader:243:41)
at async onImport.tracePromise.__proto__ (node:internal/modules/esm/loader:546:25)

Update

I tried a different package named module-federation-vite which doesn't instantly return the previous error, but instead returns the error below.

[vite] Error when evaluating SSR module /node_modules/__mf__virtual/b__loadRemote__a_mf_1_Heading__loadRemote__.js:
|- ReferenceError: require is not defined
at eval (/app/b/node_modules/__mf__virtual/b__loadRemote__a_mf_1_Heading__loadRemote__.js?v=7ceca39b:4:26)
at instantiateModule (file:///app/b/node_modules/vite/dist/node/chunks/dep-mCdpKltl.js:52650:11)

When I navigate to node_modules/_mf__virtual/b__loadRemote__a_mf_1_Heading__loadRemote_.js, then I see the code below. The issue is that it uses require. All the other files in the same __mf__virtual directory use import, so I don't know why this one uses require. Anyone have any idea?

const {loadRemote} = require("@module-federation/runtime")
const {initPromise} = require("__mf__virtual/b__mf_v__runtimeInit__mf_v__.js")
const res = initPromise.then(_ => loadRemote("a/Heading"))
const exportModule = /*mf top-level-await placeholder replacement mf*/initPromise.then(_ => res)
module.exports = exportModule

The remote side Vite configuration is the same as before. Here is my updated plugin configuration for the module-federation-vite plugin on the host side:

plugins: [qwikCity(), qwikVite(), tsconfigPaths(), federation({
    name: "b",
    remotes: {
        a: {
            type: 'module',
            name: 'a',
            entry: 'http://localhost:5173/dist/assets/remoteEntry.js',
            entryGlobalName: 'a',
            shareScope: "default"
        }
    },
    filename: "remoteEntry.js",
})],

Upvotes: 2

Views: 42

Answers (0)

Related Questions