Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: exclude version ranges from federation #17425

Open
wants to merge 50 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
50 commits
Select commit Hold shift click to select a range
f097be1
feat: add version exclusion
tmpaul Jun 21, 2023
3c6910d
chore: add test case for exclusion
tmpaul Jun 21, 2023
84a3fc3
chore: adjust warnings
tmpaul Jun 21, 2023
b684b01
chore: add additional statements to test
tmpaul Jun 21, 2023
c398bb5
chore: adjust test case
tmpaul Jun 23, 2023
ad0657b
chore(deps-dev): bump eslint-plugin-jest from 27.2.1 to 27.2.2
dependabot[bot] Jun 20, 2023
1477416
fix: require.context and layer
alexander-akait Jun 15, 2023
4a27246
test: update
alexander-akait Jun 15, 2023
aec247b
test: added
alexander-akait Jun 15, 2023
43ec503
test: fixed
alexander-akait Jun 15, 2023
15399c6
test: fix name and bug in test
alexander-akait Jun 15, 2023
563c6ac
fix: runtime for CSS loading
alexander-akait Jun 19, 2023
831094e
test: fix
alexander-akait Jun 21, 2023
213b01b
feat: use css/auto as default css type
Jun 18, 2023
91309bf
test: update snapshots
Jun 18, 2023
c6767ff
refactor: rewrite defaults
Jun 19, 2023
d20a11f
test: update snapshots
Jun 19, 2023
b62b334
test: update tests
Jun 19, 2023
2046031
test: update snapshots
Jun 19, 2023
b5daf64
feat: update regex to match valid css file names
Jun 19, 2023
f0b3556
test: add tests for module extensions
Jun 19, 2023
e299975
test: fix tests
Jun 20, 2023
90472f8
test: prefer relative
alexander-akait Jun 20, 2023
babf240
fix: bug with css/auto
alexander-akait Jun 20, 2023
8d31b66
fix: indirect call to tagged template expression
alexander-akait Jun 17, 2023
dd75c40
refactor(types): fix
alexander-akait Jun 17, 2023
417fea9
fix: update environment support for KaiOS browser
steverep Jun 17, 2023
30ae157
test: update
alexander-akait Jun 18, 2023
fbaafa7
fix: tla for await won't run
ahabhgk Jun 16, 2023
f90cc6e
fix: forgot .d
ahabhgk Jun 16, 2023
6cd441a
fix: test
ahabhgk Jun 16, 2023
82fcfb2
move test to async-modules case
ahabhgk Jun 16, 2023
85858f6
update test
ahabhgk Jun 16, 2023
c2019c3
docs: add example for stats minimal output
ersachin3112 Jun 20, 2023
c268246
chore: fix lint
ersachin3112 Jun 21, 2023
0236599
chore: fix lint
ersachin3112 Jun 21, 2023
02e93e9
chore: fix lint
ersachin3112 Jun 21, 2023
034a8eb
refactor(types): more
alexander-akait Jun 16, 2023
65313c6
refactor(types): more
alexander-akait Jun 16, 2023
a9f661a
refactor(types): more
alexander-akait Jun 16, 2023
dfa531c
refactor(types): more
alexander-akait Jun 16, 2023
487ba3e
refactor(types): more
alexander-akait Jun 16, 2023
cbd3c88
refactor(types): more
alexander-akait Jun 16, 2023
8429fad
refactor(types): more
alexander-akait Jun 17, 2023
ac68a79
5.88.0
TheLarkInn Jun 21, 2023
683bb8f
chore: merge main branch
tmpaul Jun 23, 2023
4a3cc04
fix: use fallback version in consume shared
tmpaul Jun 26, 2023
9735e40
chore(lint): Add description in schema
tmpaul Jun 26, 2023
6be2a1a
chore(lint): update consume shared
tmpaul Jun 26, 2023
35f67c0
chore: merge upstream
tmpaul Jul 2, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fix: use fallback version in consume shared
  • Loading branch information
tmpaul committed Jun 26, 2023
commit 4a3cc04977a47dd3810c6156bc0a937c7f28f907
4 changes: 2 additions & 2 deletions declarations/plugins/container/ModuleFederationPlugin.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 278,7 @@ export interface SharedConfig {
*/
eager?: boolean;
/**
* A set of exclusion criterias to use to decide if a module must participate in sharing.
* A set of exclusion criteria to use to decide if a module must participate in sharing.
*/
exclusionCriteria?: SharedExclusionCriteria;
/**
Expand Down Expand Up @@ -315,7 315,7 @@ export interface SharedConfig {
version?: false | string;
}
/**
* A set of exclusion criterias to use to decide if a module must participate in sharing.
* A set of exclusion criteria to use to decide if a module must participate in sharing.
*/
export interface SharedExclusionCriteria {
/**
Expand Down
21 changes: 16 additions & 5 deletions declarations/plugins/sharing/ConsumeSharedPlugin.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 43,7 @@ export interface ConsumesConfig {
* Include the fallback module directly instead behind an async request. This allows to use fallback module in initial load too. All possible shared modules need to be eager too.
*/
eager?: boolean;
/**
* A set of exclusion criterias to use to decide if a module must participate in sharing.
*/
exclusionCriteria?: SharedExclusionCriteria;
exclusionCriteria?: SharedExclusionCriteriaWithFallbackVersion;
/**
* Fallback module if no shared module is found in share scope. Defaults to the property name.
*/
Expand Down Expand Up @@ -77,7 74,21 @@ export interface ConsumesConfig {
strictVersion?: boolean;
}
/**
* A set of exclusion criterias to use to decide if a module must participate in sharing.
* This interface was referenced by `ConsumeSharedPluginOptions`'s JSON-Schema
* via the `definition` "SharedExclusionCriteriaWithFallbackVersion".
*/
export interface SharedExclusionCriteriaWithFallbackVersion {
/**
* Version of the package provided by the fallback if there is one.
*/
fallbackVersion?: string;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adds a new property called fallbackVersion, which is only exposed to ConsumeSharedPlugin. It is not directly accessible to ModuleFederationPlugin consumers. The value of this property is the truthy value of version property passed to ModuleFederationPlugin.

/**
* A version or semver range of the dependency to exclude from sharing.
*/
version?: string;
}
/**
* A set of exclusion criteria to use to decide if a module must participate in sharing.
*/
export interface SharedExclusionCriteria {
/**
Expand Down
4 changes: 2 additions & 2 deletions declarations/plugins/sharing/ProvideSharedPlugin.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 41,7 @@ export interface ProvidesConfig {
*/
eager?: boolean;
/**
* A set of exclusion criterias to use to decide if a module must participate in sharing.
* A set of exclusion criteria to use to decide if a module must participate in sharing.
*/
exclusionCriteria?: SharedExclusionCriteria;
/**
Expand All @@ -58,7 58,7 @@ export interface ProvidesConfig {
version?: false | string;
}
/**
* A set of exclusion criterias to use to decide if a module must participate in sharing.
* A set of exclusion criteria to use to decide if a module must participate in sharing.
*/
export interface SharedExclusionCriteria {
/**
Expand Down
4 changes: 2 additions & 2 deletions declarations/plugins/sharing/SharePlugin.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 44,7 @@ export interface SharedConfig {
*/
eager?: boolean;
/**
* A set of exclusion criterias to use to decide if a module must participate in sharing.
* A set of exclusion criteria to use to decide if a module must participate in sharing.
*/
exclusionCriteria?: SharedExclusionCriteria;
/**
Expand Down Expand Up @@ -81,7 81,7 @@ export interface SharedConfig {
version?: false | string;
}
/**
* A set of exclusion criterias to use to decide if a module must participate in sharing.
* A set of exclusion criteria to use to decide if a module must participate in sharing.
*/
export interface SharedExclusionCriteria {
/**
Expand Down
2 changes: 1 addition & 1 deletion lib/sharing/ConsumeSharedModule.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 16,8 @@ const makeSerializable = require("../util/makeSerializable");
const { rangeToString, stringifyHoley } = require("../util/semver");
const ConsumeSharedFallbackDependency = require("./ConsumeSharedFallbackDependency");

/** @typedef {import("../../declarations/plugins/sharing/SharePlugin").SharedExclusionCriteria} SharedExclusionCriteria */
/** @typedef {import("../../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptions */
/** @typedef {import("../../declarations/plugins/sharing/ConsumeSharedPlugin").SharedExclusionCriteriaWithFallbackVersion} SharedExclusionCriteria */
/** @typedef {import("../ChunkGraph")} ChunkGraph */
/** @typedef {import("../ChunkGroup")} ChunkGroup */
/** @typedef {import("../Compilation")} Compilation */
Expand Down
42 changes: 30 additions & 12 deletions lib/sharing/ConsumeSharedPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 4,7 @@
*/

"use strict";

const path = require("path");
const ModuleNotFoundError = require("../ModuleNotFoundError");
const RuntimeGlobals = require("../RuntimeGlobals");
Expand Down Expand Up @@ -255,28 256,45 @@ class ConsumeSharedPlugin {
requiredVersion
}
);
// Check if exclusion criteria is provided
if (config.exclusionCriteria && config.exclusionCriteria.version) {
const exclusionCriteriaWarning = details => {
const error = new WebpackError(
`Error while attempting to decide exclusion criteria with version: ${config.exclusionCriteria.version}. ${details}`
);
error.file = `shared module ${request}`;
compilation.warnings.push(error);
};
// Without a resolved import, we cannot proceed with exclusion check
if (!importResolved) {
return consumedModule;
}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, we check if importResolved can be mapped out. If there is no resolved import path for a request, we cannot decide whether to exclude it from sharing, so by default include it.

// If a fallback version is provided by the user, use that to check
if (config.exclusionCriteria.fallbackVersion) {
if (
satisfy(
parseRange(config.exclusionCriteria.version),
config.exclusionCriteria.fallbackVersion
)
) {
return undefined;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If user has supplied a version property to ModuleFed plugin, use that to check against the exclusionCriteria.version range

}
return consumedModule;
}
return new Promise(resolve => {
// Get the closest package.json file corresponding to the resolved import.
// This version will be used for checking whether the dependency must be
// excluded from consumption (in a share context). If such a version does
// not exist in the package.json file, then we use the "version" property
// set by users in the share config, which is passed here as fallbackVersion
// a.k.a the version used to register the package in the scope.
getDescriptionFile(
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Find the closest package.json for the resolved import. This gives us the version of the package/module that corresponds to the request. Note that there are shared modules that do not have a corresponding package.json file, and for these, we do not exclude them from sharing unless the user supplies a version property. If that is the case, the check in line 269 will activate

compilation.inputFileSystem,
path.dirname(importResolved),
["package.json"],
(err, result) => {
if (err) {
console.error(err);
return resolve(consumedModule);
}
const { data } = result;
if (!data) {
exclusionCriteriaWarning(
`Unable to find description file in ${importResolved}.`
);
if (
!data ||
(data && !data.version) ||
(data && data.name !== request)
) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check that the package.json name matches the requested module. Otherwise it can resolve to the root package.json of the project.

// If we cannot determine exclusion, return the consumed module
return resolve(consumedModule);
}
Expand Down
10 changes: 8 additions & 2 deletions lib/sharing/SharePlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 8,7 @@
const { parseOptions } = require("../container/options");
const ConsumeSharedPlugin = require("./ConsumeSharedPlugin");
const ProvideSharedPlugin = require("./ProvideSharedPlugin");
const { isRequiredVersion } = require("./utils");
const { isRequiredVersion, validateShareOptions } = require("./utils");

/** @typedef {import("../../declarations/plugins/sharing/ConsumeSharedPlugin").ConsumeSharedPluginOptions} ConsumeSharedPluginOptions */
/** @typedef {import("../../declarations/plugins/sharing/ConsumeSharedPlugin").ConsumesConfig} ConsumesConfig */
Expand Down Expand Up @@ -43,13 43,19 @@ class SharePlugin {
},
item => item
);
validateShareOptions(sharedOptions);
/** @type {Record<string, ConsumesConfig>[]} */
const consumes = sharedOptions.map(([key, options]) => ({
[key]: {
import: options.import,
shareKey: options.shareKey || key,
shareScope: options.shareScope,
exclusionCriteria: options.exclusionCriteria,
exclusionCriteria: options.exclusionCriteria
? {
...options.exclusionCriteria,
fallbackVersion: options.version ? options.version : undefined
}
: undefined,
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pass in version as fallbackVersion to exclusionCriteria. As far a consumed module is concerned, the version property represents the version of the fallback.

requiredVersion: options.requiredVersion,
strictVersion: options.strictVersion,
singleton: options.singleton,
Expand Down
19 changes: 19 additions & 0 deletions lib/sharing/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 8,7 @@
const { join, dirname, readJson } = require("../util/fs");

/** @typedef {import("../util/fs").InputFileSystem} InputFileSystem */
/** @typedef {import("../../declarations/plugins/sharing/SharePlugin").SharedConfig} SharedConfig */

// Extreme shorthand only for github. eg: foo/bar
const RE_URL_GITHUB_EXTREME_SHORT = /^[^/@:.\s][^/@:\s]*\/[^@:\s]*[^/@:\s]#\S /;
Expand Down Expand Up @@ -310,6 311,24 @@ function isRequiredVersion(str) {
return VERSION_PATTERN_REGEXP.test(str);
}

/**
* Additional validation logic for share options
* @param {[string, SharedConfig][]} options options
*/
function validateShareOptions(options) {
for (let [key, option] of options) {
if (!!option.exclusionCriteria && option.singleton === true) {
throw new Error(
`Cannot supply exclusionCriteria and singleton: true together for ${key} in shared configuration.
Please set singleton: false or remove the exclusionCriteria from shared config
`
);
}
}
}

exports.validateShareOptions = validateShareOptions;

exports.isRequiredVersion = isRequiredVersion;

/**
Expand Down
Loading