-
Notifications
You must be signed in to change notification settings - Fork 59
fix: #156 ssr: require is not defined #250
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
As mentioned here: module-federation#156 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @poenneby for your help 🤗
@gioboa Running the multi-example with these changes correctly The transpiled code that causes the error: // node_modules/__mf__virtual/host__loadRemote__remote_mf_1_Product__loadRemote__.js
var import_node_module = __toESM(require_node_module());
var { loadRemote } = require2("@module-federation/runtime");
var { initPromise } = require2("__mf__virtual/host__mf_v__runtimeInit__mf_v__.js");
var res = initPromise.then((_) => loadRemote("remote/Product"));
var exportModule = (
/*mf top-level-await placeholder replacement mf*/
initPromise.then((_) => res)
);
var require2 = (0, import_node_module.createRequire)(import.meta.url);
var host_loadRemote_remote_mf_1_Product_loadRemote_default = exportModule;
const __mfproxy__awaitdefault = await default(); <-- HERE
const __mfproxy__default = () => __mfproxy__awaitdefault;
export { __mfproxy__default as default }; Any ideas? |
I see, I will check it. Thanks for the deep investigation |
Hey @gioboa any update on this? |
I did look at it yet. But eventually we can continually change the code if an SSR env is detected |
Hey @gioboa ! Are you looking at this. Would be happy to help but I am struggling to understand the inner workings. Thanks! |
Not yet but I will look at it. Can you share your repository to test this change please? |
Here you go! https://github.com/poenneby/mf-vanilla-react-router |
Hi @poenneby. I'm trying to do the same as you. I fond this issue and started some investigation. I don't think you can rely on checking the remote type for esm. This would work if the exported code would only run on SSR. But that module can be requested by the browser directly, as in the failing test. So to make it compatible with client-side rendering it needs to use syntax supported in CJS. Even if we fix the top-level await issue, the import from 'node:module' wouldn't work in this scenario. I guess the ideal solution would be use a syntax supported both by CJS and ESM (which is easier said than done). I think we can try using dynamic imports and runtime check on the exports. something like this: export function generateRemotes(id: string, command: string) {
return `
const runtimePromise = import('@module-federation/runtime');
const virtualRuntimePromise = import("${virtualRuntimeInitStatus.getImportId()}");
const res = Promise.all([runtimePromise, virtualRuntimePromise])
.then(([runtime, virtualRuntime]) => {
const initPromise = virtualRuntime.initPromise;
return initPromise.then(() => runtime.loadRemote(${JSON.stringify(id)}));
});
const exportModule = ${command !== 'build' ? '/*mf top-level-await placeholder replacement mf*/' : 'await '}res;
// Dual exports for CJS/ESM compatibility
if (typeof module !== 'undefined') {
module.exports = exportModule;
module.exports.default = exportModule;
}
// ESM export fallback
if (typeof exports !== 'undefined' && typeof define !== 'function') {
Object.defineProperty(exports, '__esModule', { value: true });
exports.default = exportModule;
}
`;
} This is passing the current tests. Other than that I think we would need to figure out a way to properly identify the runtime (CJS/ESM) instead of the relying on the remote type. EDIT: This also seems to break the toplevel await plugin logic. |
Another idea is to use a plugin (https://github.com/originjs/vite-plugins/tree/main/packages/vite-plugin-commonjs) to convert CJS to ESM on the host doing SSR and requesting the module. |
ok... this is a slightly modified code, that doesn't seem to affect top level await logic: export function generateRemotes(id: string, command: string) {
return `
const runtimePromise = import('@module-federation/runtime');
const virtualRuntimePromise = import("${virtualRuntimeInitStatus.getImportId()}");
const res = Promise.all([runtimePromise, virtualRuntimePromise])
.then(([runtime, virtualRuntime]) => {
const initPromise = virtualRuntime.initPromise;
return initPromise.then(() => runtime.loadRemote(${JSON.stringify(id)}));
});
const exportModule = ${command !== 'build' ? '/*mf top-level-await placeholder replacement mf*/' : 'await '}res;
// Dual exports for CJS/ESM compatibility
module.exports = exportModule;
module.exports.default = exportModule;
// ESM export fallback
const _exports = exports || {};
Object.defineProperty(_exports, '__esModule', { value: true });
exports.default = exportModule;
`;
} but the weird thing is that now the build fails, from what it seems like we want the top level await transform to do.
Not sure what's happening and why we need the top level await logic exactly. |
@poenneby I think I have a slightly better understanding of it now. We were making it harder than it had to be. We don't have to make the exports esm compatible. Rollup will process the file before writing it, and wrap the code into a So, I think we only need to get rid of the I've got a fork for this here :https://github.com/tiagobnobrega/mf-vite/tree/interop Haven't tested on SSR yet. I'll try to make progress on that if I find the time. |
Is there any update on this? |
im running into a related issue that may require the use of esm import() vs require. It seems that there is an edge case that can cause an import cycle, and as cjs gets rewritten to esm, the page hangs b/c a module waits on a promise that loads a chunk that goes and ends up requesting itself... So far rewriting |
Sorry. I had to move focus elsewhere. I'm still interested in this, but it is more complex than I anticipated. I found issues with top-level await in ESM modules. I was looking at the runtime packages, maybe this could leverage that ecosystem more. |
Further to this discussion: #156 (comment)