Skip to content

Commit 10e6f5a

Browse files
feat(webpack-bundler-runtime): create container function (#2440)
Co-authored-by: ScriptedAlchemy <[email protected]>
1 parent 103b2b8 commit 10e6f5a

File tree

5 files changed

+263
-2
lines changed

5 files changed

+263
-2
lines changed

.changeset/new-eyes-hang.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@module-federation/webpack-bundler-runtime': patch
3+
---
4+
5+
createContainer factory function added. Allows container interfaced to be dynamically created

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
"app:next:prod": "nx run-many --target=serve --configuration=production -p 3000-home,3001-shop,3002-checkout",
3939
"app:node:dev": "nx run-many --target=serve --parallel=10 --configuration=development -p node-host,node-local-remote,node-remote,node-dynamic-remote-new-version,node-dynamic-remote",
4040
"app:runtime:dev": "nx run-many --target=serve -p 3005-runtime-host,3006-runtime-remote,3007-runtime-remote",
41-
"app:manifest:dev": "nx run-many --target=serve --parallel=10 -p 3008-webpack-host,3009-webpack-provider,3010-rspack-provider,3011-rspack-manifest-provider,3012-rspack-js-entry-provider",
41+
"app:manifest:dev": "nx run-many --target=serve --parallel=100 -p 3008-webpack-host,3009-webpack-provider,3010-rspack-provider,3011-rspack-manifest-provider,3012-rspack-js-entry-provider",
4242
"app:ts:dev": "nx run-many --target=serve -p react_ts_host,react_ts_nested_remote,react_ts_remote",
4343
"commitlint": "commitlint --edit",
4444
"prepare": "husky install",

packages/webpack-bundler-runtime/package.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@
3232
"import": "./dist/constant.esm.js",
3333
"require": "./dist/constant.cjs.js"
3434
},
35+
"./container": {
36+
"import": "./dist/container.esm.js",
37+
"require": "./dist/container.cjs.js"
38+
},
3539
"./*": "./*"
3640
},
3741
"typesVersions": {
@@ -43,5 +47,8 @@
4347
"./dist/constant.cjs.d.ts"
4448
]
4549
}
50+
},
51+
"devDependencies": {
52+
"@module-federation/runtime": "workspace:*"
4653
}
4754
}

packages/webpack-bundler-runtime/project.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
"compiler": "swc",
1818
"format": ["cjs", "esm"],
1919
"additionalEntryPoints": [
20-
"packages/webpack-bundler-runtime/src/constant.ts"
20+
"packages/webpack-bundler-runtime/src/constant.ts",
21+
"packages/webpack-bundler-runtime/src/container.ts"
2122
],
2223
"external": ["@module-federation/*"],
2324
"buildableProjectDepsInPackageJsonType": "dependencies",
Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
import bundler_runtime_base from './index';
2+
import type { UserOptions } from '@module-federation/runtime/types';
3+
4+
interface ExtendedOptions extends UserOptions {
5+
exposes: { [key: string]: () => Promise<() => any> };
6+
}
7+
8+
export const createContainer = (federationOptions: ExtendedOptions) => {
9+
const { exposes, name, remotes = [], shared, plugins } = federationOptions;
10+
11+
const __webpack_modules__ = {
12+
'./node_modules/.federation/entry.1f2288102e035e2ed66b2efaf60ad043.js': (
13+
//@ts-ignore
14+
module,
15+
//@ts-ignore
16+
__webpack_exports__,
17+
//@ts-ignore
18+
__webpack_require__,
19+
) => {
20+
__webpack_require__.r(__webpack_exports__);
21+
const bundler_runtime = __webpack_require__.n(bundler_runtime_base);
22+
const prevFederation = __webpack_require__.federation;
23+
__webpack_require__.federation = {};
24+
for (const key in bundler_runtime()) {
25+
__webpack_require__.federation[key] = bundler_runtime()[key];
26+
}
27+
for (const key in prevFederation) {
28+
__webpack_require__.federation[key] = prevFederation[key];
29+
}
30+
if (!__webpack_require__.federation.instance) {
31+
const pluginsToAdd = plugins || [];
32+
__webpack_require__.federation.initOptions.plugins = __webpack_require__
33+
.federation.initOptions.plugins
34+
? __webpack_require__.federation.initOptions.plugins.concat(
35+
pluginsToAdd,
36+
)
37+
: pluginsToAdd;
38+
__webpack_require__.federation.instance =
39+
__webpack_require__.federation.runtime.init(
40+
__webpack_require__.federation.initOptions,
41+
);
42+
if (__webpack_require__.federation.attachShareScopeMap) {
43+
__webpack_require__.federation.attachShareScopeMap(
44+
__webpack_require__,
45+
);
46+
}
47+
if (__webpack_require__.federation.installInitialConsumes) {
48+
__webpack_require__.federation.installInitialConsumes();
49+
}
50+
}
51+
},
52+
//@ts-ignore
53+
'webpack/container/entry/createContainer': (
54+
//@ts-ignore
55+
56+
module,
57+
//@ts-ignore
58+
exports,
59+
//@ts-ignore
60+
__webpack_require__,
61+
) => {
62+
const moduleMap = {};
63+
for (const key in exposes) {
64+
if (Object.prototype.hasOwnProperty.call(exposes, key)) {
65+
//@ts-ignore
66+
moduleMap[key] = () =>
67+
Promise.resolve(exposes[key]()).then((m) => () => m);
68+
}
69+
}
70+
//@ts-ignore
71+
const get = (module, getScope) => {
72+
__webpack_require__.R = getScope;
73+
getScope = __webpack_require__.o(moduleMap, module)
74+
? //@ts-ignore
75+
moduleMap[module]()
76+
: Promise.resolve().then(() => {
77+
throw new Error(
78+
`Module "${module}" does not exist in container.`,
79+
);
80+
});
81+
__webpack_require__.R = undefined;
82+
return getScope;
83+
};
84+
//@ts-ignore
85+
const init = (shareScope, initScope, remoteEntryInitOptions) => {
86+
return __webpack_require__.federation.bundlerRuntime.initContainerEntry(
87+
{
88+
webpackRequire: __webpack_require__,
89+
shareScope: shareScope,
90+
initScope: initScope,
91+
remoteEntryInitOptions: remoteEntryInitOptions,
92+
shareScopeKey: 'default',
93+
},
94+
);
95+
};
96+
__webpack_require__(
97+
'./node_modules/.federation/entry.1f2288102e035e2ed66b2efaf60ad043.js',
98+
);
99+
100+
// This exports getters to disallow modifications
101+
__webpack_require__.d(exports, {
102+
get: () => get,
103+
init: () => init,
104+
moduleMap: () => moduleMap,
105+
});
106+
},
107+
};
108+
109+
const __webpack_module_cache__ = {};
110+
111+
//@ts-ignore
112+
const __webpack_require__ = (moduleId) => {
113+
//@ts-ignore
114+
let cachedModule = __webpack_module_cache__[moduleId];
115+
if (cachedModule !== undefined) {
116+
return cachedModule.exports;
117+
}
118+
//@ts-ignore
119+
let module = (__webpack_module_cache__[moduleId] = {
120+
id: moduleId,
121+
loaded: false,
122+
exports: {},
123+
});
124+
125+
const execOptions = {
126+
id: moduleId,
127+
module: module,
128+
//@ts-ignore
129+
factory: __webpack_modules__[moduleId],
130+
require: __webpack_require__,
131+
};
132+
__webpack_require__.i.forEach((handler) => {
133+
handler(execOptions);
134+
});
135+
module = execOptions.module;
136+
execOptions.factory.call(
137+
module.exports,
138+
module,
139+
module.exports,
140+
execOptions.require,
141+
);
142+
143+
module.loaded = true;
144+
145+
return module.exports;
146+
};
147+
148+
__webpack_require__.m = __webpack_modules__;
149+
__webpack_require__.c = __webpack_module_cache__;
150+
//@ts-ignore
151+
__webpack_require__.i = [];
152+
153+
//@ts-ignore
154+
if (!__webpack_require__.federation) {
155+
__webpack_require__.federation = {
156+
initOptions: {
157+
name: name,
158+
//@ts-ignore
159+
remotes: remotes.map((remote) => ({
160+
type: remote.type,
161+
alias: remote.alias,
162+
name: remote.name,
163+
//@ts-ignore
164+
entry: remote.entry,
165+
shareScope: remote.shareScope || 'default',
166+
})),
167+
},
168+
chunkMatcher: () => true,
169+
rootOutputDir: '',
170+
initialConsumes: undefined,
171+
bundlerRuntimeOptions: {},
172+
};
173+
}
174+
//@ts-ignore
175+
__webpack_require__.n = (module) => {
176+
const getter =
177+
module && module.__esModule ? () => module['default'] : () => module;
178+
__webpack_require__.d(getter, { a: getter });
179+
return getter;
180+
};
181+
182+
//@ts-ignore
183+
__webpack_require__.d = (exports, definition) => {
184+
for (const key in definition) {
185+
if (
186+
__webpack_require__.o(definition, key) &&
187+
!__webpack_require__.o(exports, key)
188+
) {
189+
Object.defineProperty(exports, key, {
190+
enumerable: true,
191+
get: definition[key],
192+
});
193+
}
194+
}
195+
};
196+
197+
__webpack_require__.f = {};
198+
199+
__webpack_require__.g = (() => {
200+
if (typeof globalThis === 'object') return globalThis;
201+
try {
202+
return this || new Function('return this')();
203+
} catch (e) {
204+
if (typeof window === 'object') return window;
205+
}
206+
})();
207+
208+
//@ts-ignore
209+
__webpack_require__.o = (obj, prop) =>
210+
Object.prototype.hasOwnProperty.call(obj, prop);
211+
//@ts-ignore
212+
__webpack_require__.r = (exports) => {
213+
if (typeof Symbol !== 'undefined' && Symbol.toStringTag) {
214+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
215+
}
216+
Object.defineProperty(exports, '__esModule', { value: true });
217+
};
218+
219+
//@ts-ignore
220+
__webpack_require__.federation.initOptions.shared = shared;
221+
__webpack_require__.S = {};
222+
const initPromises = {};
223+
const initTokens = {};
224+
//@ts-ignore
225+
__webpack_require__.I = (name, initScope) => {
226+
//@ts-ignore
227+
return __webpack_require__.federation.bundlerRuntime.I({
228+
shareScopeName: name,
229+
webpackRequire: __webpack_require__,
230+
initPromises: initPromises,
231+
initTokens: initTokens,
232+
initScope: initScope,
233+
});
234+
};
235+
236+
const __webpack_exports__ = __webpack_require__(
237+
'webpack/container/entry/createContainer',
238+
);
239+
const __webpack_exports__get = __webpack_exports__.get;
240+
const __webpack_exports__init = __webpack_exports__.init;
241+
return __webpack_exports__;
242+
};
243+
export const createContainerAsync = async (
244+
federationOptions: ExtendedOptions,
245+
) => {
246+
// todo: consider async startup options here, for "async boundary" provision.
247+
return createContainer(federationOptions);
248+
};

0 commit comments

Comments
 (0)