Skip to content

Commit 4a6beb0

Browse files
feat(enhanced): add experiments.aliasConsumption flag; remove env toggle
- Gate alias-aware consuming behind experiments.aliasConsumption (opt-in) - Remove FEDERATION_ALIAS_CONSUMPTION env usage - Update schemas for MF/Share/Consume plugins - Forward aliasConsumption only when defined - Enhanced tests passing locally
2 parents d4be790 + 65812e4 commit 4a6beb0

23 files changed

+544
-486
lines changed

packages/enhanced/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787
"@types/btoa": "^1.2.5",
8888
"ajv": "^8.17.1",
8989
"enhanced-resolve": "^5.0.0",
90+
"memfs": "^4.36.0",
9091
"terser": "^5.37.0"
9192
},
9293
"dependencies": {

packages/enhanced/src/declarations/plugins/sharing/ConsumeSharedPlugin.d.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ export interface ConsumeSharedPluginOptions {
2525
* Share scope name used for all consumed modules (defaults to 'default').
2626
*/
2727
shareScope?: string | string[];
28+
/**
29+
* Experimental features configuration.
30+
*/
31+
experiments?: {
32+
/** Enable alias-aware consuming via NormalModuleFactory.afterResolve (experimental). */
33+
aliasConsumption?: boolean;
34+
};
2835
}
2936
/**
3037
* Modules that should be consumed from share scope. Property names are used to match requested modules in this compilation. Relative requests are resolved, module requests are matched unresolved, absolute paths will match resolved requests. A trailing slash will match all requests with this prefix. In this case shareKey must also have a trailing slash.

packages/enhanced/src/declarations/plugins/sharing/SharePlugin.d.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ export interface SharePluginOptions {
2525
* Modules that should be shared in the share scope. When provided, property names are used to match requested modules in this compilation.
2626
*/
2727
shared: Shared;
28+
/**
29+
* Experimental features configuration.
30+
*/
31+
experiments?: {
32+
/** Enable alias-aware consuming via NormalModuleFactory.afterResolve (experimental). */
33+
aliasConsumption?: boolean;
34+
};
2835
}
2936
/**
3037
* Modules that should be shared in the share scope. Property names are used to match requested modules in this compilation. Relative requests are resolved, module requests are matched unresolved, absolute paths will match resolved requests. A trailing slash will match all requests with this prefix. In this case shareKey must also have a trailing slash.

packages/enhanced/src/lib/container/ModuleFederationPlugin.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ class ModuleFederationPlugin implements WebpackPluginInstance {
107107
(new RemoteEntryPlugin(options) as unknown as WebpackPluginInstance).apply(
108108
compiler,
109109
);
110+
111+
// Do not use process.env for alias consumption; flag is forwarded via options
110112
if (options.experiments?.provideExternalRuntime) {
111113
if (options.exposes) {
112114
throw new Error(
@@ -212,10 +214,18 @@ class ModuleFederationPlugin implements WebpackPluginInstance {
212214
}).apply(compiler);
213215
}
214216
if (options.shared) {
215-
new SharePlugin({
217+
// build SharePlugin options and forward aliasConsumption only when defined
218+
const sharePluginOptions: import('../../declarations/plugins/sharing/SharePlugin').SharePluginOptions & {
219+
experiments?: { aliasConsumption?: boolean };
220+
} = {
216221
shared: options.shared,
217222
shareScope: options.shareScope,
218-
}).apply(compiler);
223+
};
224+
const aliasConsumption = options.experiments?.aliasConsumption;
225+
if (typeof aliasConsumption === 'boolean') {
226+
sharePluginOptions.experiments = { aliasConsumption };
227+
}
228+
new SharePlugin(sharePluginOptions).apply(compiler);
219229
}
220230
});
221231

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ const PLUGIN_NAME = 'ConsumeSharedPlugin';
8282

8383
class ConsumeSharedPlugin {
8484
private _consumes: [string, ConsumeOptions][];
85+
private _aliasConsumption: boolean;
8586

8687
constructor(options: ConsumeSharedPluginOptions) {
8788
if (typeof options !== 'string') {
@@ -157,6 +158,13 @@ class ConsumeSharedPlugin {
157158
} as ConsumeOptions;
158159
},
159160
);
161+
162+
// read experiments flag if provided via options
163+
// typings may not include experiments yet; cast to any
164+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
165+
this._aliasConsumption = Boolean(
166+
(options as any)?.experiments?.aliasConsumption,
167+
);
160168
}
161169

162170
createConsumeSharedModule(
@@ -698,7 +706,8 @@ class ConsumeSharedPlugin {
698706
);
699707

700708
// AFTER RESOLVE: alias-aware equality (single-resolution per candidate via cache)
701-
{
709+
// Guarded by experimental flag provided via options
710+
if (this._aliasConsumption) {
702711
const afterResolveHook = (normalModuleFactory as any)?.hooks
703712
?.afterResolve;
704713
if (afterResolveHook?.tapPromise) {

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,16 @@ const validate = createSchemaValidation(
2828
},
2929
);
3030

31+
type ShareExperiments = {
32+
allowNodeModulesSuffixMatch?: boolean;
33+
aliasConsumption?: boolean;
34+
};
35+
3136
class SharePlugin {
3237
private _shareScope: string | string[];
3338
private _consumes: Record<string, ConsumesConfig>[];
3439
private _provides: Record<string, ProvidesConfig>[];
40+
private _experiments?: ShareExperiments;
3541

3642
constructor(options: SharePluginOptions) {
3743
validate(options);
@@ -98,6 +104,9 @@ class SharePlugin {
98104
this._shareScope = options.shareScope || 'default';
99105
this._consumes = consumes;
100106
this._provides = provides;
107+
// keep experiments object if present (validated by schema)
108+
// includes allowNodeModulesSuffixMatch and aliasConsumption (experimental)
109+
this._experiments = options.experiments as ShareExperiments | undefined;
101110
}
102111

103112
/**
@@ -111,6 +120,8 @@ class SharePlugin {
111120
new ConsumeSharedPlugin({
112121
shareScope: this._shareScope,
113122
consumes: this._consumes,
123+
// forward experiments to ConsumeSharedPlugin
124+
experiments: this._experiments,
114125
}).apply(compiler);
115126

116127
new ProvideSharedPlugin({

0 commit comments

Comments
 (0)