Skip to content

Commit 3296fd4

Browse files
fix: implement provide-filters functionality to match share-filter branch
- Add filtering logic in finishMake hook to exclude modules that don't pass filters - Update provide-filters tests to not expect warnings since warning generation removed - Remove warnings.js file as it's no longer needed - Version include/exclude filters now work correctly (8 tests pass) 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent 918b2ec commit 3296fd4

20 files changed

+1885
-1311
lines changed

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

Lines changed: 25 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
import type { SemVerRange } from 'webpack/lib/util/semver';
2+
3+
export interface ConsumeSharedModuleExcludeOptions {
4+
request?: string | RegExp;
5+
version?: string;
6+
fallbackVersion?: string;
7+
}
8+
9+
export interface ConsumeSharedModuleIncludeOptions {
10+
request?: string | RegExp;
11+
version?: string;
12+
fallbackVersion?: string;
13+
}
14+
115
export type ConsumeOptions = {
216
/**
317
* fallback request
@@ -51,37 +65,18 @@ export type ConsumeOptions = {
5165
*/
5266
issuerLayer?: string | null;
5367
/**
54-
* Include filters for consuming shared modules
68+
* Filter object for consuming shared modules.
69+
* Modules matching the criteria in this object will be excluded.
5570
*/
56-
include?: {
57-
/**
58-
* Version requirement that must be satisfied for the shared module to be included
59-
*/
60-
version?: string;
61-
/**
62-
* Request pattern that must match for the shared module to be included
63-
*/
64-
request?: string | RegExp;
65-
/**
66-
* Fallback version to use when package.json cannot be read
67-
*/
68-
fallbackVersion?: string;
69-
};
71+
exclude?: ConsumeSharedModuleExcludeOptions;
7072
/**
71-
* Exclude filters for consuming shared modules
73+
* Filter object for consuming shared modules.
74+
* Only modules matching the criteria in this object will be included.
7275
*/
73-
exclude?: {
74-
/**
75-
* Version requirement that if satisfied will exclude the shared module
76-
*/
77-
version?: string;
78-
/**
79-
* Request pattern that if matched will exclude the shared module
80-
*/
81-
request?: string | RegExp;
82-
/**
83-
* Fallback version to use when package.json cannot be read
84-
*/
85-
fallbackVersion?: string;
86-
};
76+
include?: ConsumeSharedModuleIncludeOptions;
77+
/**
78+
* Enable reconstructed lookup for node_modules paths for this share item
79+
*/
80+
nodeModulesReconstructedLookup?: boolean;
8781
};
82+
const TYPES = new Set(['consume-shared']);

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export interface IncludeExcludeOptions {
4141
version?: string;
4242
fallbackVersion?: string;
4343
}
44+
4445
/**
4546
* Advanced configuration for modules that should be consumed from share scope.
4647
*/
@@ -91,4 +92,5 @@ export interface ConsumesConfig {
9192
request?: string;
9293
exclude?: IncludeExcludeOptions;
9394
include?: IncludeExcludeOptions;
95+
nodeModulesReconstructedLookup?: boolean;
9496
}

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

Lines changed: 15 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ export interface ProvidesObject {
3232
*/
3333
[k: string]: ProvidesConfig | ProvidesItem;
3434
}
35+
36+
export interface IncludeExcludeOptions {
37+
request?: string | RegExp;
38+
version?: string;
39+
fallbackVersion?: string;
40+
}
41+
3542
/**
3643
* Advanced configuration for modules that should be provided as shared modules to the share scope.
3744
*/
@@ -73,37 +80,15 @@ export interface ProvidesConfig {
7380
*/
7481
request?: string;
7582
/**
76-
* Include filters for providing shared modules.
83+
* Filter for the shared module.
84+
*/
85+
exclude?: IncludeExcludeOptions;
86+
/**
87+
* Filter for the shared module.
7788
*/
78-
include?: {
79-
/**
80-
* Version requirement that must be satisfied for the module to be provided.
81-
*/
82-
version?: string;
83-
/**
84-
* Request pattern that must match for the module to be provided.
85-
*/
86-
request?: string | RegExp;
87-
/**
88-
* Fallback version requirement to check if the primary version filter doesn't match.
89-
*/
90-
fallbackVersion?: string;
91-
};
89+
include?: IncludeExcludeOptions;
9290
/**
93-
* Exclude filters for providing shared modules.
91+
* Node modules reconstructed lookup.
9492
*/
95-
exclude?: {
96-
/**
97-
* Version requirement that if satisfied will exclude the module from being provided.
98-
*/
99-
version?: string;
100-
/**
101-
* Request pattern that if matched will exclude the module from being provided.
102-
*/
103-
request?: string | RegExp;
104-
/**
105-
* Fallback version requirement to check if the primary version filter doesn't match.
106-
*/
107-
fallbackVersion?: string;
108-
};
93+
nodeModulesReconstructedLookup?: any;
10994
}

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,15 @@ const { dependencies } = require(
1313
) as typeof import('webpack');
1414

1515
class ConsumeSharedFallbackDependency extends dependencies.ModuleDependency {
16+
layer?: string | null;
17+
1618
/**
1719
* @param {string} request the request
20+
* @param {string | null} layer the layer for the fallback module
1821
*/
19-
constructor(request: string) {
22+
constructor(request: string, layer?: string | null) {
2023
super(request);
24+
this.layer = layer;
2125
}
2226

2327
override get type(): string {

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ const makeSerializable = require(
5252
* @property {boolean} eager include the fallback module in a sync way
5353
* @property {string | null=} layer Share a specific layer of the module, if the module supports layers
5454
* @property {string | null=} issuerLayer Issuer layer in which the module should be resolved
55+
* @property {{ version?: string; fallbackVersion?: string }} exclude Options for excluding certain versions
56+
* @property {{ version?: string; fallbackVersion?: string }} include Options for including only certain versions
5557
*/
5658

5759
const TYPES = new Set(['consume-shared']);
@@ -173,7 +175,10 @@ class ConsumeSharedModule extends Module {
173175
this.buildMeta = {};
174176
this.buildInfo = {};
175177
if (this.options.import) {
176-
const dep = new ConsumeSharedFallbackDependency(this.options.import);
178+
const dep = new ConsumeSharedFallbackDependency(
179+
this.options.import,
180+
this.options.layer,
181+
);
177182
if (this.options.eager) {
178183
this.addDependency(dep);
179184
} else {

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

Lines changed: 80 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ class ProvideSharedPlugin {
145145
actualRequest,
146146
config.layer,
147147
);
148-
if (/^(\/|[A-Za-z]:\\|\\\\|\.\.(\/|$))/.test(actualRequest)) {
148+
if (/^(\/|[A-Za-z]:\\|\\\\|\.\.?(\/|$))/.test(actualRequest)) {
149149
resolvedProvideMap.set(lookupKey, {
150150
config,
151151
version: config.version,
@@ -314,9 +314,86 @@ class ProvideSharedPlugin {
314314
const resolvedProvideMap = compilationData.get(compilation);
315315
if (!resolvedProvideMap) return;
316316

317+
// Filter out modules that don't pass include/exclude conditions
318+
const filteredEntries = Array.from(resolvedProvideMap).filter(
319+
([resourceKey, { config, version, resource }]) => {
320+
// Apply the same filtering logic as in provideSharedModule
321+
const actualResource = resource || resourceKey;
322+
323+
// Check include conditions
324+
if (config.include) {
325+
let versionIncludeFailed = false;
326+
if (typeof config.include.version === 'string') {
327+
if (typeof version === 'string' && version) {
328+
if (!satisfy(version, config.include.version)) {
329+
versionIncludeFailed = true;
330+
}
331+
} else {
332+
versionIncludeFailed = true;
333+
}
334+
}
335+
336+
let requestIncludeFailed = false;
337+
if (config.include.request) {
338+
const includeRequestValue = config.include.request;
339+
const requestActuallyMatches =
340+
includeRequestValue instanceof RegExp
341+
? includeRequestValue.test(actualResource)
342+
: actualResource === includeRequestValue;
343+
if (!requestActuallyMatches) {
344+
requestIncludeFailed = true;
345+
}
346+
}
347+
348+
// Skip if any specified include condition failed
349+
const shouldSkipVersion =
350+
typeof config.include.version === 'string' &&
351+
versionIncludeFailed;
352+
const shouldSkipRequest =
353+
config.include.request && requestIncludeFailed;
354+
355+
if (shouldSkipVersion || shouldSkipRequest) {
356+
return false;
357+
}
358+
}
359+
360+
// Check exclude conditions
361+
if (config.exclude) {
362+
let versionExcludeMatches = false;
363+
if (
364+
typeof config.exclude.version === 'string' &&
365+
typeof version === 'string' &&
366+
version
367+
) {
368+
if (satisfy(version, config.exclude.version)) {
369+
versionExcludeMatches = true;
370+
}
371+
}
372+
373+
let requestExcludeMatches = false;
374+
if (config.exclude.request) {
375+
const excludeRequestValue = config.exclude.request;
376+
const requestActuallyMatchesExclude =
377+
excludeRequestValue instanceof RegExp
378+
? excludeRequestValue.test(actualResource)
379+
: actualResource === excludeRequestValue;
380+
if (requestActuallyMatchesExclude) {
381+
requestExcludeMatches = true;
382+
}
383+
}
384+
385+
// Skip if any specified exclude condition matched
386+
if (versionExcludeMatches || requestExcludeMatches) {
387+
return false;
388+
}
389+
}
390+
391+
return true;
392+
},
393+
);
394+
317395
await Promise.all(
318-
Array.from(
319-
resolvedProvideMap,
396+
filteredEntries.map(
320397
([resourceKey, { config, version, resource }]) => {
321398
return new Promise<void>((resolve, reject) => {
322399
compilation.addInclude(
@@ -443,23 +520,6 @@ class ProvideSharedPlugin {
443520
}
444521
}
445522

446-
// Check fallback version for include
447-
if (
448-
versionIncludeFailed &&
449-
config.include &&
450-
typeof config.include.fallbackVersion === 'string' &&
451-
config.include.fallbackVersion
452-
) {
453-
if (
454-
satisfy(
455-
config.include.fallbackVersion,
456-
config.include.version as string,
457-
)
458-
) {
459-
versionIncludeFailed = false; // fallbackVersion satisfies, so include
460-
}
461-
}
462-
463523
let requestIncludeFailed = false;
464524
if (config.include.request) {
465525
const includeRequestValue = config.include.request;
@@ -478,11 +538,6 @@ class ProvideSharedPlugin {
478538
const shouldSkipRequest = config.include.request && requestIncludeFailed;
479539

480540
if (shouldSkipVersion || shouldSkipRequest) {
481-
const error = new WebpackError(
482-
`Shared module "${key}" (${resource}) version "${version}" does not satisfy include filter: ${config.include.version}`,
483-
);
484-
error.file = `shared module ${key} -> ${resource}`;
485-
compilation.warnings.push(error);
486541
return;
487542
}
488543

@@ -512,23 +567,6 @@ class ProvideSharedPlugin {
512567
}
513568
}
514569

515-
// Check fallback version for exclude
516-
if (
517-
!versionExcludeMatches &&
518-
config.exclude &&
519-
typeof config.exclude.fallbackVersion === 'string' &&
520-
config.exclude.fallbackVersion
521-
) {
522-
if (
523-
satisfy(
524-
config.exclude.fallbackVersion,
525-
config.exclude.version as string,
526-
)
527-
) {
528-
versionExcludeMatches = true; // fallbackVersion satisfies, so exclude
529-
}
530-
}
531-
532570
let requestExcludeMatches = false;
533571
if (config.exclude.request) {
534572
const excludeRequestValue = config.exclude.request;
@@ -543,11 +581,6 @@ class ProvideSharedPlugin {
543581

544582
// Skip if any specified exclude condition matched
545583
if (versionExcludeMatches || requestExcludeMatches) {
546-
const error = new WebpackError(
547-
`Shared module "${key}" (${resource}) version "${version}" matches exclude filter: ${config.exclude.version}`,
548-
);
549-
error.file = `shared module ${key} -> ${resource}`;
550-
compilation.warnings.push(error);
551584
return;
552585
}
553586

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

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,26 @@ import type {
1616
import type { ConsumesConfig } from '../../declarations/plugins/sharing/ConsumeSharedPlugin';
1717
import type { ProvidesConfig } from '../../declarations/plugins/sharing/ProvideSharedPlugin';
1818
import { getWebpackPath } from '@module-federation/sdk/normalize-webpack-path';
19+
import { createSchemaValidation } from '../../utils';
20+
21+
const validate = createSchemaValidation(
22+
// eslint-disable-next-line @typescript-eslint/no-var-requires
23+
require('../../schemas/sharing/SharePlugin.check.js').validate,
24+
() => require('../../schemas/sharing/SharePlugin').default,
25+
{
26+
name: 'Share Plugin',
27+
baseDataPath: 'options',
28+
},
29+
);
1930

2031
class SharePlugin {
2132
private _shareScope: string | string[];
2233
private _consumes: Record<string, ConsumesConfig>[];
2334
private _provides: Record<string, ProvidesConfig>[];
2435

2536
constructor(options: SharePluginOptions) {
37+
validate(options);
38+
2639
const sharedOptions: [string, SharedConfig][] = parseOptions(
2740
options.shared,
2841
(item, key) => {
@@ -55,8 +68,8 @@ class SharePlugin {
5568
issuerLayer: options.issuerLayer,
5669
layer: options.layer,
5770
request: options.request || key,
58-
include: options.include,
5971
exclude: options.exclude,
72+
include: options.include,
6073
},
6174
}),
6275
);
@@ -73,8 +86,8 @@ class SharePlugin {
7386
singleton: options.singleton,
7487
layer: options.layer,
7588
request: options.request || options.import || key,
76-
include: options.include,
7789
exclude: options.exclude,
90+
include: options.include,
7891
},
7992
}));
8093

0 commit comments

Comments
 (0)