Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
4ba90f1
fix(runtime): use runtime script loader in node federation
ScriptedAlchemy Jan 16, 2024
3bd30b1
fix(nextjs-mf): remove federation utils from eager sharing
ScriptedAlchemy Jan 16, 2024
a58ed5a
ci: improve e2e stability
ScriptedAlchemy Jan 16, 2024
c947895
ci: improve e2e stability
ScriptedAlchemy Jan 16, 2024
ac5e515
ci: improve e2e stability
ScriptedAlchemy Jan 16, 2024
838dda9
Merge branch 'main' into feat/use-runtime-script-load
ScriptedAlchemy Jan 16, 2024
fc29816
fix: remove more delegate code from next package
ScriptedAlchemy Jan 16, 2024
6e0cef8
feat: support cjs (#1981)
2heal1 Jan 17, 2024
5bb5861
fix: remove logs
ScriptedAlchemy Jan 17, 2024
f2f71f1
Revert "feat: support cjs (#1981)"
ScriptedAlchemy Jan 20, 2024
7a6f7d9
Merge branch 'main' into feat/use-runtime-script-load
ScriptedAlchemy Jan 20, 2024
0235e43
Merge branch 'main' into feat/use-runtime-script-load
ScriptedAlchemy Jan 20, 2024
bcc1be9
Merge branch 'main' into feat/use-runtime-script-load
ScriptedAlchemy Jan 20, 2024
f3c43f0
Merge branch 'main' into feat/use-runtime-script-load
ScriptedAlchemy Jan 23, 2024
215cccc
feat: initRawContainer method (#2011)
ScriptedAlchemy Jan 23, 2024
2fd3c2a
fix(node): ensure global container ref as fallback
ScriptedAlchemy Jan 23, 2024
fa7cfac
test: e2e for node federation remote types
ScriptedAlchemy Jan 23, 2024
05d86fc
fix(node): check for internal runtime id before patching user options
ScriptedAlchemy Jan 23, 2024
42bb39d
test: add e2e for node federation
ScriptedAlchemy Jan 23, 2024
d47403a
Merge branch 'main' into feat/use-runtime-script-load
ScriptedAlchemy Feb 27, 2024
60d2e81
fix(node): runtime script load to use api
ScriptedAlchemy Feb 27, 2024
120bd53
fix(nextjs-mf): fix static method function proxy assignment
ScriptedAlchemy Mar 6, 2024
ce66efb
Merge branch 'main' into feat/use-runtime-script-load
ScriptedAlchemy Mar 6, 2024
913bf74
Merge branch 'main' into fix/next-proxy-method-runtime-plugin
ScriptedAlchemy Mar 7, 2024
951e66e
Merge branch 'main' into fix/next-proxy-method-runtime-plugin
ScriptedAlchemy Mar 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/gold-cherries-stare.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@module-federation/nextjs-mf': patch
---

Fix issue with function proxy not returning static methods
85 changes: 63 additions & 22 deletions packages/nextjs-mf/src/plugins/container/runtimePlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,33 +72,74 @@ export default function (): FederationRuntimePlugin {
},
onLoad(args) {
const { exposeModuleFactory, exposeModule, id } = args;

const moduleOrFactory = exposeModuleFactory || exposeModule;
const exposedModuleExports = moduleOrFactory();
const handler = {
//@ts-ignore
get: function (target, prop, receiver) {
const origMethod = target[prop];
if (typeof origMethod === 'function') {
//@ts-ignore
return function (...args) {
globalThis.usedChunks.add(
//@ts-ignore
id,
);
if (!moduleOrFactory) return; // Ensure moduleOrFactory is defined
let exposedModuleExports: any = moduleOrFactory();

if (typeof window === 'undefined') {
const handler: ProxyHandler<any> = {
get(target, prop, receiver) {
// Check if accessing a static property of the function itself
if (
target === exposedModuleExports &&
typeof exposedModuleExports[prop] === 'function'
) {
return function (this: unknown, ...args: any[]) {
globalThis.usedChunks.add(id);
return exposedModuleExports[prop].apply(this, args);
};
}

const originalMethod = target[prop];
if (typeof originalMethod === 'function') {
const proxiedFunction = function (this: unknown, ...args: any[]) {
globalThis.usedChunks.add(id);
return originalMethod.apply(this, args);
};

// Copy all enumerable properties from the original method to the proxied function
Object.keys(originalMethod).forEach((prop) => {
Object.defineProperty(proxiedFunction, prop, {
value: originalMethod[prop],
writable: true,
enumerable: true,
configurable: true,
});
});

return proxiedFunction;
}

// console.log(`function as called to ${prop}`, id);
//@ts-ignore
return origMethod.apply(this, args);
};
} else {
return Reflect.get(target, prop, receiver);
}
},
};
},
};

if (typeof exposedModuleExports === 'function') {
// If the module export is a function, we create a proxy that can handle both its
// call (as a function) and access to its properties (including static methods).
exposedModuleExports = new Proxy(exposedModuleExports, handler);

// Proxy static properties specifically
const staticProps = Object.getOwnPropertyNames(exposedModuleExports);
staticProps.forEach((prop) => {
if (typeof exposedModuleExports[prop] === 'function') {
exposedModuleExports[prop] = new Proxy(
exposedModuleExports[prop],
handler,
);
}
});
} else {
// For objects, just wrap the exported object itself
exposedModuleExports = new Proxy(exposedModuleExports, handler);
}

return () => new Proxy(exposedModuleExports, handler);
return () => exposedModuleExports;
}

return args;
},

resolveShare(args) {
if (
args.pkgName !== 'react' &&
Expand Down