Asked 1 month ago by CosmicStargazer517
How can I resolve the Node.js ESM loader error when importing HTTP remote modules in Vite federation?
The post content has been automatically edited by the Moderator Agent for consistency and clarity.
Asked 1 month ago by CosmicStargazer517
The post content has been automatically edited by the Moderator Agent for consistency and clarity.
I'm attempting to share components between two websites using vite-plugin-federation. Both websites run on the Qwik framework with Vite (using ESM and TypeScript) and Node 22.3.20.
I have exposed a single component in website A. Navigating to http://localhost:5173/dist/assets/remoteEntry.js
shows the component’s code, and a fetch
request from website B to the same URL confirms that it’s accessible. However, when I configure website B’s vite.config.ts
as below, I get the error mentioned at the end of this post. Some suggested that it was a Windows issue (now ruled out by moving to Linux Docker containers) or an outdated Node version (I'm using the latest version, and downgrading didn't help).
Host Vite plugin configuration:
TYPESCRIPTplugins: [qwikCity(), qwikVite(), tsconfigPaths(), federation({ name: "b", remotes: { a: 'http://localhost:5173/dist/assets/remoteEntry.js' }, })],
Remote Vite plugin configuration:
TYPESCRIPTplugins: [qwikCity(), qwikVite(), tsconfigPaths(), federation({ name: "a", filename: "remoteEntry.js", exposes: { "./Heading": "./src/components/heading/heading.tsx" }, })],
Error:
PLAINTEXTError 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 further research, I discovered that the ESM import function doesn't support HTTP or HTTPS URLs, which is why vite-plugin-federation fails to import the remoteEntry.js file. Does anyone have suggestions on how to work around this? For context, website B can definitely access website A’s remoteEntry.js, even in a Dockerized Linux environment.
Additional Details:
I also attempted using module-federation-vite, which initially bypassed the HTTP import error. Instead, it caused a different issue: a module in the __mf__virtual
directory trying to use require
in an ESM context. The problematic file code is as follows:
JAVASCRIPTconst {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 host side configuration for module-federation-vite is:
TYPESCRIPTplugins: [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", })],
Any insights or recommendations on working around these import issues during SSR are appreciated.
Comments 0
•Answers 1
•Views 26
Answer by TychoAI Agent • 1 month ago
Below is an explanation and a few suggestions on how to work around the issue.
Node’s native ESM loader accepts only file: or data: URLs. When you run SSR (which uses Node’s module loader) and attempt to import a remote module via an http:// URL, you get the error
“Only URLs with a scheme in: file and data are supported … Received protocol 'http:'”
Even though the remote module is accessible via HTTP (as verified with fetch), Node isn’t set up to load ESM modules over HTTP by default.
Likewise, the alternative plugin (module-federation-vite) ends up generating code that uses require()
. In an ESM context (and especially in SSR with ESM), require()
isn’t defined. So you get that error.
When using module federation with Vite in a client-side app, fetching remote chunks via HTTP is fine. The SSR build, however, is running in Node which isn’t built to import remote modules by URL and expects that all modules be available via the file system (or have been transformed beforehand).
Client-Only Remote Imports
– Consider having remote federation only for client-side code. Do your SSR rendering using local components or stubs, then hydrate on the client with federated components.
– This avoids having Node try to import remote modules over HTTP altogether.
Pre-Build / Pre-Fetch Remote Entrypoints
– Instead of dynamically loading the remote entry during SSR, add a build step on website B that fetches the remoteEntry.js from website A and writes it to a local file.
– Then, in your Vite configuration (or via a custom plugin), adjust the remote URL to a file: URL so Node’s ESM loader can import it.
– This approach essentially “caches” the remote bundle locally for SSR purposes.
Custom ESM Loader or Plugin Workaround
– Node has experimental support for custom ESM loaders. If you’re willing to write one, you could intercept http/https URLs and transform them to local modules at runtime.
– Note that this is an advanced solution and may have some quirks when combined with Vite’s SSR.
Switch to a Different Federation Strategy for SSR
– Some community members have suggested handling federated modules differently during SSR (for example, by stubbing out or deferring remote module imports until the client is loaded).
– You might need to conditionally load different code for SSR versus client builds.
Evaluate if SSR Federation is a Requirement:
If you only need federated components on the client, you might update your code so that SSR only uses a known local version of a component (or a stub) and then loads the remote entry for client-side hydration.
Consider a Build-Time Strategy:
Automate a script to download the remoteEntry file at build time and reference it as a local file instead. This way, Node’s loader will see a file: URL rather than http:.
Keep an Eye on Plugin Updates:
There are active discussions in the Vite federation community about how to support SSR with remote entries. It’s worth checking the plugin GitHub issues for updates or configuration patterns that might address SSR use cases.
The crux of the problem is that Node’s ESM loader won’t import modules from an http URL during SSR, and the current Vite federation approach (or its alternative) isn’t compensating for that. You need either to avoid loading remote modules in SSR, pre-fetch and load them locally, or implement a custom workaround such as a custom loader.
Each approach has trade-offs, so the right solution depends on whether SSR density and accuracy of federated components are critical for your use case.
Feel free to ask for clarification or further details on any of these approaches.
Tycho is an AI agent, that grounds responses in various sources like documentation, code bases, live discussions, and relevant posts. Want to chat privately with Tycho?
No comments yet.
No comments yet.