Skip to content

Commit 0c665be

Browse files
feat(enhanced): layers support in module code generation (#3371)
1 parent 243f1bc commit 0c665be

25 files changed

+350
-11
lines changed

packages/enhanced/src/lib/sharing/ProvideSharedModule.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ class ProvideSharedModule extends Module {
212212
requiredVersion: this._requiredVersion,
213213
strictVersion: this._strictVersion,
214214
singleton: this._singleton,
215+
layer: this.layer
215216
},
216217
});
217218
return { sources, data, runtimeRequirements };

packages/enhanced/src/lib/sharing/ProvideSharedModuleFactory.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class ProvideSharedModuleFactory extends ModuleFactory {
3939
dep.requiredVersion,
4040
dep.strictVersion,
4141
dep.singleton,
42+
dep.layer
4243
),
4344
});
4445
}

packages/enhanced/src/lib/sharing/ProvideSharedPlugin.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ class ProvideSharedPlugin {
265265
config.requiredVersion!,
266266
config.strictVersion!,
267267
config.singleton!,
268+
config.layer
268269
),
269270
{
270271
name: undefined,

packages/enhanced/src/lib/sharing/ShareRuntimeModule.ts

Lines changed: 51 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,14 @@ class ShareRuntimeModule extends RuntimeModule {
7474
if (sharedOption) {
7575
sharedInitOptions[sharedOption.name] =
7676
sharedInitOptions[sharedOption.name] || [];
77-
const isSameVersion = sharedInitOptions[sharedOption.name].find(
78-
(s) => s.version === sharedOption.version,
77+
const isSameVersionAndLayer = sharedInitOptions[
78+
sharedOption.name
79+
].find(
80+
(s) =>
81+
s.version === sharedOption.version &&
82+
s.shareConfig?.layer === sharedOption.shareConfig?.layer,
7983
);
80-
if (!isSameVersion) {
84+
if (!isSameVersionAndLayer) {
8185
sharedInitOptions[sharedOption.name].push(sharedOption);
8286
}
8387
}
@@ -88,18 +92,19 @@ class ShareRuntimeModule extends RuntimeModule {
8892
(sum, sharedName) => {
8993
const sharedOptions = sharedInitOptions[sharedName];
9094
let str = '';
91-
sharedOptions.forEach((sharedOption) => {
95+
96+
// Ensure all options are included without filtering
97+
sharedOptions.forEach((option) => {
9298
str += `{${Template.indent([
93-
`version: ${sharedOption.version},`,
94-
`get: ${sharedOption.getter},`,
95-
`scope: ${JSON.stringify(sharedOption.shareScope)},`,
96-
`shareConfig: ${JSON.stringify(sharedOption.shareConfig)}`,
99+
`version: ${option.version},`,
100+
`get: ${option.getter},`,
101+
`scope: ${JSON.stringify(option.shareScope)},`,
102+
`shareConfig: ${JSON.stringify(option.shareConfig)}`,
97103
])}},`;
98104
});
99-
str = `[${str}]`;
100105

106+
str = `[${str}]`;
101107
sum += `${Template.indent([`"${sharedName}": ${str},`])}`;
102-
103108
return sum;
104109
},
105110
'',
@@ -108,6 +113,42 @@ class ShareRuntimeModule extends RuntimeModule {
108113
const federationGlobal = getFederationGlobalScope(
109114
RuntimeGlobals || ({} as typeof RuntimeGlobals),
110115
);
116+
117+
// Group shared modules by scope and layer
118+
const scopedModules = new Map<
119+
string,
120+
Map<string | undefined, Set<string>>
121+
>();
122+
for (const [scopeName, stages] of initCodePerScope) {
123+
const layeredModules = new Map<string | undefined, Set<string>>();
124+
scopedModules.set(scopeName, layeredModules);
125+
126+
for (const [, inits] of stages) {
127+
for (const init of inits) {
128+
const layer = init.match(/layer:\s*["']([^"']+)["']/)?.[1];
129+
let moduleSet = layeredModules.get(layer);
130+
if (!moduleSet) {
131+
moduleSet = new Set();
132+
layeredModules.set(layer, moduleSet);
133+
}
134+
moduleSet.add(init);
135+
}
136+
}
137+
}
138+
139+
// Generate the registration code
140+
const registrationCode = Array.from(scopedModules.entries())
141+
.map(([scopeName, layeredModules]) => {
142+
const cases = Array.from(layeredModules.entries())
143+
.map(([layer, inits]) => {
144+
const initCode = Array.from(inits).join('\n');
145+
return `case "${scopeName}": {\n${Template.indent(initCode)}\n}`;
146+
})
147+
.join('\nbreak;\n');
148+
return cases;
149+
})
150+
.join('\n');
151+
111152
return Template.asString([
112153
`${getFederationGlobalScope(
113154
RuntimeGlobals,

packages/enhanced/src/lib/sharing/utils.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*/
55

66
import { isRequiredVersion } from '@module-federation/sdk';
7-
import type { ConsumeOptions } from 'webpack/lib/sharing/ConsumeSharedModule';
7+
import type { ConsumeOptions } from '../../declarations/plugins/sharing/ConsumeSharedModule';
88
import { normalizeWebpackPath } from '@module-federation/sdk/normalize-webpack-path';
99
import type { InputFileSystem } from 'webpack/lib/util/fs';
1010
const { join, dirname, readJson } = require(
@@ -459,6 +459,7 @@ export function normalizeConsumeShareOptions(consumeOptions: ConsumeOptions) {
459459
eager,
460460
shareKey,
461461
shareScope,
462+
layer,
462463
} = consumeOptions;
463464
return {
464465
shareConfig: {
@@ -467,6 +468,7 @@ export function normalizeConsumeShareOptions(consumeOptions: ConsumeOptions) {
467468
strictVersion,
468469
singleton,
469470
eager,
471+
layer,
470472
},
471473
shareScope,
472474
shareKey,
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import React from 'react';
2+
import ComponentA from 'containerA/ComponentA';
3+
import ComponentALayers from 'containerA/ComponentALayers';
4+
5+
export default () => {
6+
return `App rendered with [${React()}], [${ComponentA()}] and [${ComponentALayers()}]`;
7+
};
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import React from 'react';
2+
3+
export default () => {
4+
return `ComponentA rendered with [${React()}]`;
5+
};
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import * as React from 'react';
2+
3+
export default () => {
4+
debugger;
5+
return `ComponentALayers rendered with [${React.layeredComponentsReact()}]`;
6+
};
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
it('should load the component from container', () => {
2+
return import('./App').then(({ default: App }) => {
3+
const rendered = App();
4+
expect(rendered).toBe(
5+
'App rendered with [This is react 0.1.2], [ComponentA rendered with [This is react 0.1.2]] and [ComponentALayers rendered with [This is layered react]]',
6+
);
7+
return import('./upgrade-react').then(({ default: upgrade }) => {
8+
upgrade();
9+
const rendered = App();
10+
expect(rendered).toBe(
11+
'App rendered with [This is react 1.2.3], [ComponentA rendered with [This is react 1.2.3]] and [ComponentALayers rendered with [This is layered react]]',
12+
);
13+
});
14+
});
15+
});
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module.exports = function (source) {
2+
console.log(source);
3+
return source.replace('__PLACEHOLDER__', 'This is layered react');
4+
};

0 commit comments

Comments
 (0)