✨ Vite 7 Support
Describe the bug
error during build:
Build failed with 1 error:
[plugin vite:oxc-transpile]
Error: `await` is only allowed within async functions and at the top levels of modules
11 | requiredVersion: "18"
12 | } } }));
13 | const exportModule = await res.then((factory) => factory());
| ^^^^^
14 | module.exports = exportModule;
15 | });
at transformWithOxc
This is connected to https://github.com/module-federation/vite/blob/e7ff316cc6c073224007dcbc39914dc94f20a077/src/virtualModules/virtualShared_preBuild.ts#L39
I have tried to debug further but vite 7 is making it extremely hard to breakpoint and debug inside the plugin. So it is unclear if I will be able to get a solution if I can't do so.
I am unsure also what has changed. The info I was able to extract though is the following from the vite-vite/vite-host example app:
import { __commonJSMin } from "./chunk-!~{004}~.js";
import { require_index_cjs, require_viteViteHost__mf_v__runtimeInit__mf_v__ } from "./viteViteHost__mf_v__runtimeInit__mf_v__-!~{008}~.js";
//#region node_modules/__mf__virtual/viteViteHost__loadShare__react__loadShare__.js
var require_viteViteHost__loadShare__react__loadShare__ = __commonJSMin((exports, module) => {
const { loadShare } = require_index_cjs();
const { initPromise } = require_viteViteHost__mf_v__runtimeInit__mf_v__();
const res = initPromise.then((_) => loadShare("react", { customShareInfo: { shareConfig: {
singleton: false,
strictVersion: false,
requiredVersion: "18"
} } }));
const exportModule = await res.then((factory) => factory());
module.exports = exportModule;
});
//#endregion
export { require_viteViteHost__loadShare__react__loadShare__ };
What stands out is the __commonJSMin wrapper being used which is a core entity/mechanism in rolldown https://github.com/rolldown/rolldown/blob/9c158fe6aa9296b0da53ec044dcfa78014e0f629/crates/rolldown/src/runtime/index.js#L22 . Unclear why its getting done like this, but the current approach has some clear issues with v7.
Version
7.0.10
Reproduction
n/a
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.
Thanks for your report @pcfreak30 This plugin is not tested with Vite v7 in fact we have another issue similar to this #315
Thanks for your report @pcfreak30 This plugin is not tested with Vite v7 in fact we have another issue similar to this #315
Yes im aware, but that is just a types issue, not a runtime issue.
This would very likely also make it compatible with rolldown-vite, which will be upon us officially soon enough... After using rolldown-vite it is extremely hard to justify using anything else... Vite is often an order of magnitude faster than other similar tools, and on my relatively complex project production build literally goes from ~2minutes to ~11s with rolldown-vite. So potentially two orders of magnitude faster...
This would very likely also make it compatible with
rolldown-vite, which will be upon us officially soon enough... After usingrolldown-viteit is extremely hard to justify using anything else... Vite is often an order of magnitude faster than other similar tools, and on my relatively complex project production build literally goes from ~2minutes to ~11s withrolldown-vite. So potentially two orders of magnitude faster...
Which is likely that as soon as rolldowns MF is feature-competitive with this plugin I will likely jump ship.
"vite": "7.1.7" works fine, everything above breaks
may switch to the default @vite/plugin-react helps, opt to plugin-react-swc, plugin-react-oxc
Additional Analysis & Workaround
I've been debugging this issue extensively with Vite 7.2.7 and @module-federation/vite 1.9.2. Here's what I found:
Two Related Issues
Issue 1: Syntax Error (what this issue describes)
Vite 7's Rolldown bundler wraps CommonJS modules with __commonJSMin((exports, module) => { ... }). The generated code in virtualShared_preBuild.ts uses:
const exportModule = await res.then((factory) => factory());
module.exports = exportModule;This puts await inside a non-async arrow function → syntax error.
Issue 2: Circular Deadlock (even if syntax issue is fixed)
When React/ReactDOM are in shared, the build creates a circular dependency:
hostInituses Vite's preload helper toimport("remoteEntry.js")- The preload helper gets bundled into the React chunk (common dependency)
- React chunk has top-level await:
await initPromise.then(runtime => runtime.loadShare("react")) initPromiseis only resolved whenremoteEntry.init()is called- DEADLOCK: React waits for remoteEntry → hostInit can't load remoteEntry until React finishes
The app shows a blank page with no console errors because the deadlock happens silently.
Workaround
Setting shared: {} bypasses both issues:
federation({
name: 'my_app',
remotes: { ... },
shared: {}, // Workaround: empty shared config
})
The MFE still loads via registerRemotes() at runtime - each app just bundles its own React. Not ideal for optimization, but functional.
The generated code in virtualShared_preBuild.ts needs to:
- Use ES module syntax instead of CommonJS (
exportinstead ofmodule.exports) - OR wrap in an async IIFE
- OR use a lazy initialization pattern that doesn't block module execution
Happy to help with a PR if maintainers can provide guidance on preferred approach.
Environment
- Vite: 7.2.7
- @module-federation/vite: 1.9.2
- React: 19.2.0
- Node: 22.x
5. DEADLOCK: React waits for remoteEntry → hostInit can't load remoteEntry until React finishes
Ive hit this type of thing before myself as I think it can happen in other cases but its, in effect, a circular dependency on the promise loading of the module system. The MFE still loads via registerRemotes() at runtime - each app just bundles its own React. For me thats a deal breaker, as I cant have that and would need to debug the import loop if it happened to me...
The generated code in
virtualShared_preBuild.tsneeds to:
- Use ES module syntax instead of CommonJS (
exportinstead ofmodule.exports)- OR wrap in an async IIFE
- OR use a lazy initialization pattern that doesn't block module execution
We need to be sure it stays working in vite 6 as well.