diff --git a/package-lock.json b/package-lock.json index 44a2944..c8f46bb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11582,7 +11582,7 @@ } }, "packages/rollup-plugin-module-federation": { - "version": "1.8.4", + "version": "1.9.0", "license": "MIT", "dependencies": { "@module-federation/runtime": "0.0.10", diff --git a/packages/examples/project-a/public/esm/index.html b/packages/examples/project-a/public/esm/index.html index 0d2b927..2a57b8d 100644 --- a/packages/examples/project-a/public/esm/index.html +++ b/packages/examples/project-a/public/esm/index.html @@ -2,82 +2,78 @@ Module Federation Experiments

Open JS console to see logs.

- Type globalThis.shareScope in the JS console to check the current state of - shared scope object. + Type __FEDERATION__.__SHARE__ in the JS console to check the current state + of shared scope object.

-
-

Check the page source or code below to see what's happening

-
-      
+ + + + + +
- diff --git a/packages/examples/project-a/public/system/index.html b/packages/examples/project-a/public/system/index.html index 0b32421..0a484cd 100644 --- a/packages/examples/project-a/public/system/index.html +++ b/packages/examples/project-a/public/system/index.html @@ -11,6 +11,9 @@ */ uuid: { '9.0.0': { + /** + * Return a factory that returns a Promise which returns a factory which returns the module + */ get: () => Promise.resolve(() => ({ v4: () => globalThis.crypto.randomUUID(), @@ -27,59 +30,77 @@ window.location.href.lastIndexOf('/'), ); const remoteEntryUrl = `${basePath}/my-remote-entry.js`; - /** - * Import the remote container using SystemJS as it's output format is system. - */ - const container = await System.import(remoteEntryUrl); - console.log('doing container.init()'); - await container.init(sharedScope); - console.log('shared scope: ', JSON.stringify(sharedScope, null, 2)); + let container = null; - console.log("doing container.get('./react')"); - const react = (await container.get('./react'))(); - console.log('exposed module ./react: ', react); - console.log('shared scope: ', JSON.stringify(sharedScope, null, 2)); + document + .getElementById('load-remote-a') + .addEventListener('click', async () => { + container = await System.import(remoteEntryUrl); + console.log('Loaded remote entry for project-a: ', container); + }); - console.log("doing container.get('./index')"); - const index = (await container.get('./index'))(); - console.log('exposed module ./index', index); + document + .getElementById('init-remote-a') + .addEventListener('click', async () => { + console.log('doing container.init()'); + await container.init(sharedScope); + console.log('shared scope: ', __FEDERATION__.__SHARE__); + }); - console.log('calling doSomething() from the exposed module ./index'); - await index.doSomething(); + document + .getElementById('load-exposed-react') + .addEventListener('click', async () => { + console.log("doing container.get('./react')"); + const react = (await container.get('./react'))(); + console.log('exposed module ./react: ', react); + }); - console.log("doing container.get('./pqr')"); - const pqr = (await container.get('./pqr'))(); - console.log('exposed module ./pqr', pqr); + let index = null; + document + .getElementById('load-exposed-index') + .addEventListener('click', async () => { + console.log("doing container.get('./index')"); + index = (await container.get('./index'))(); + console.log('exposed module ./index', index); + }); + + document + .getElementById('execute-doSomething-index') + .addEventListener('click', async () => { + console.log('calling doSomething() from the exposed module ./index'); + await index.doSomething(); + }); + + document + .getElementById('load-exposed-pqr') + .addEventListener('click', async () => { + console.log("doing container.get('./pqr')"); + const pqr = (await container.get('./pqr'))(); + console.log('exposed module ./pqr', pqr); + });

Open JS console to see logs.

- Type globalThis.shareScope in the JS console to check the current state of - shared scope object. + Type __FEDERATION__.__SHARE__ in the JS console to check the current state + of shared scope object.

-
-

Check the page source or code below to see what's happening

-
-      
+ + + + + +
- diff --git a/packages/examples/project-b/public/esm/index.html b/packages/examples/project-b/public/esm/index.html index 048f841..09a45d2 100644 --- a/packages/examples/project-b/public/esm/index.html +++ b/packages/examples/project-b/public/esm/index.html @@ -3,33 +3,60 @@ Module Federation Experiments + -

View page source to see what's happening

Open JS console to see logs.

- Type globalThis.shareScope in the JS console to check the current state of - shared scope object. + Type __FEDERATION__.__SHARE__ in the JS console to check the current state + of shared scope object.

+
+ + + + +
diff --git a/packages/examples/project-b/public/system/index.html b/packages/examples/project-b/public/system/index.html index d8ea2aa..63338a0 100644 --- a/packages/examples/project-b/public/system/index.html +++ b/packages/examples/project-b/public/system/index.html @@ -5,33 +5,60 @@ + -

View page source to see what's happening

Open JS console to see logs.

- Type globalThis.shareScope in the JS console to check the current state of - shared scope object. + Type __FEDERATION__.__SHARE__ in the JS console to check the current state + of shared scope object.

+
+ + + + +
diff --git a/packages/rollup-plugin-module-federation/src/index.ts b/packages/rollup-plugin-module-federation/src/index.ts index 60d83f6..080b7b8 100644 --- a/packages/rollup-plugin-module-federation/src/index.ts +++ b/packages/rollup-plugin-module-federation/src/index.ts @@ -343,9 +343,6 @@ export default function federation( moduleNameOrPath, type, } of federatedModules) { - /** - * Rollup might use its own or other registered resolvers (like @rollup/plugin-node-resolve) to resolve this. - */ if (type === 'remote') { federatedModuleInfo[moduleName] = { name: moduleName, @@ -358,6 +355,9 @@ export default function federation( }; continue; } + /** + * Rollup might use its own or other registered resolvers (like @rollup/plugin-node-resolve) to resolve this. + */ /* eslint-disable-next-line no-await-in-loop */ const resolvedId = await this.resolve(moduleNameOrPath); const resolvedModulePath = getModulePathFromResolvedId( @@ -444,9 +444,18 @@ export default function federation( * init(): Populate the shared scope object. * get(): Resolve the module which is requested. */ - const remoteEntryCode = ` - import { init as initModuleFederationRuntime } from '@module-federation/runtime'; - ${Object.entries(initConfig?.shared ?? {}) + const remoteEntryCode = new MagicString(''); + /** + * We use @module-federation/runtime for initializing and managing the container. + */ + remoteEntryCode.append( + `import { init as initModuleFederationRuntime } from '@module-federation/runtime';`, + ); + /** + * Statically import shared modules which are declared as eager + */ + remoteEntryCode.append( + Object.entries(initConfig?.shared ?? {}) .filter( ([_, sharedConfigForPkg]) => sharedConfigForPkg.shareConfig?.eager, @@ -457,12 +466,23 @@ export default function federation( */ return `import * as ${FEDERATED_EAGER_SHARED}${moduleNameOrPath} from '${moduleNameOrPath}';`; }) - .join('')} - ${runtimePlugins - ?.map((runtimePlugin, idx) => { + .join(''), + ); + /** + * Statically import the code for any runtime plugins which are registered. + */ + remoteEntryCode.append( + (runtimePlugins ?? []) + .map((runtimePlugin, idx) => { return `import ${FEDERATION_RUNTIME_PLUGIN}${idx} from '${runtimePlugin}';`; }) - .join('')} + .join(''), + ); + /** + * Implementing the init method of the container + */ + remoteEntryCode.append( + ` const init = async (sharedScope) => { const instance = await initModuleFederationRuntime({ name: '${initConfig.name}', @@ -497,47 +517,56 @@ export default function federation( * Bug: https://github.com/module-federation/universe/issues/2020 */ !shared[moduleNameOrPath]?.import - ? ` - get: () => Promise.resolve().then(() => () => null), - ` + ? `get: () => Promise.resolve().then(() => () => null),` : /** * TODO: Convert this to a lib and re-write eager shared imports to loadShareSync() */ sharedConfigForPkg.shareConfig?.eager - ? ` - get: () => Promise.resolve(${FEDERATED_EAGER_SHARED}${moduleNameOrPath}).then((module) => () => module), - ` - : ` - get: () => import('${moduleNameOrPath}').then((module) => () => module), - ` + ? `get: () => Promise.resolve(${FEDERATED_EAGER_SHARED}${moduleNameOrPath}).then((module) => () => module),` + : `get: () => import('${moduleNameOrPath}').then((module) => () => module),` } - }, - `; + },`; }) .join('')} } }); instance.initShareScopeMap('${shareScope}', sharedScope); }; - const get = (module) => { - switch(module) { - ${Object.entries(exposes) - .map( - ([key, exposedModule]) => ` - case '${key}': { - return import('${exposedModule.import}').then((module) => () => module); - } - `, - ) - .join('')} - } - }; - export { init, get }; - `; + `, + ); + /** + * Implementing the get method of the container + */ + remoteEntryCode.append( + ` + const get = (module) => { + switch(module) { + ${Object.entries(exposes) + .map( + ([key, exposedModule]) => ` + case '${key}': { + return import('${exposedModule.import}').then((module) => () => module); + }`, + ) + .join('')} + default: + throw new Error(\`Trying to get an exposed module: \$\{module\}\`); + } + }; + `, + ); + /** + * Exporting get and init. + */ + remoteEntryCode.append( + ` + export { init, get }; + `, + ); /** * TODO: We need human readable good code. Atleast until the terser plugin minifies it :p */ - return remoteEntryCode; + return remoteEntryCode.toString(); } return null; },