@module-federation/enhanced
Version:
This package provides enhanced features for module federation.
317 lines (314 loc) • 17.7 kB
JavaScript
;
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: 'Module' } });
const require_runtime = require('../../_virtual/_rolldown/runtime.js');
const require_lib_container_options = require('../container/options.js');
const require_utils = require('../../utils.js');
const require_lib_container_runtime_FederationRuntimePlugin = require('../container/runtime/FederationRuntimePlugin.js');
const require_lib_sharing_resolveMatchedConfigs = require('./resolveMatchedConfigs.js');
const require_lib_sharing_utils = require('./utils.js');
const require_lib_sharing_ConsumeSharedFallbackDependency = require('./ConsumeSharedFallbackDependency.js');
const require_lib_sharing_ConsumeSharedModule = require('./ConsumeSharedModule.js');
const require_lib_sharing_ConsumeSharedRuntimeModule = require('./ConsumeSharedRuntimeModule.js');
const require_lib_sharing_ProvideForSharedDependency = require('./ProvideForSharedDependency.js');
const require_lib_sharing_ShareRuntimeModule = require('./ShareRuntimeModule.js');
const require_schemas_sharing_ConsumeSharedPlugin_check = require('../../schemas/sharing/ConsumeSharedPlugin.check.js');
const require_schemas_sharing_ConsumeSharedPlugin = require('../../schemas/sharing/ConsumeSharedPlugin.js');
let _module_federation_sdk = require("@module-federation/sdk");
let _module_federation_sdk_normalize_webpack_path = require("@module-federation/sdk/normalize-webpack-path");
let path = require("path");
path = require_runtime.__toESM(path);
//#region src/lib/sharing/ConsumeSharedPlugin.ts
const DIRECT_FALLBACK_REGEX = /^(\.\.?(\/|$)|\/|[A-Za-z]:|\\\\)/;
const ABSOLUTE_PATH_REGEX = /^(\/|[A-Za-z]:|\\\\)/;
const RELATIVE_OR_ABSOLUTE_PATH_REGEX = /^(?:\.{1,2}[\\/]|\/|[A-Za-z]:|\\\\)/;
const PACKAGE_NAME_REGEX = /^((?:@[^\\/]+[\\/])?[^\\/]+)/;
const { satisfy, parseRange } = require((0, _module_federation_sdk_normalize_webpack_path.normalizeWebpackPath)("webpack/lib/util/semver"));
const ModuleNotFoundError = require((0, _module_federation_sdk_normalize_webpack_path.normalizeWebpackPath)("webpack/lib/ModuleNotFoundError"));
const { RuntimeGlobals } = require((0, _module_federation_sdk_normalize_webpack_path.normalizeWebpackPath)("webpack"));
const LazySet = require((0, _module_federation_sdk_normalize_webpack_path.normalizeWebpackPath)("webpack/lib/util/LazySet"));
const WebpackError = require((0, _module_federation_sdk_normalize_webpack_path.normalizeWebpackPath)("webpack/lib/WebpackError"));
const validate = require_utils.createSchemaValidation((require_schemas_sharing_ConsumeSharedPlugin_check.init_ConsumeSharedPlugin_check(), require_runtime.__toCommonJS(require_schemas_sharing_ConsumeSharedPlugin_check.ConsumeSharedPlugin_check_exports)).validate, () => (require_schemas_sharing_ConsumeSharedPlugin.init_ConsumeSharedPlugin(), require_runtime.__toCommonJS(require_schemas_sharing_ConsumeSharedPlugin.ConsumeSharedPlugin_exports)).default, {
name: "Consume Shared Plugin",
baseDataPath: "options"
});
const RESOLVE_OPTIONS = { dependencyType: "esm" };
const PLUGIN_NAME = "ConsumeSharedPlugin";
var ConsumeSharedPlugin = class {
constructor(options) {
if (typeof options !== "string") validate(options);
this._consumes = require_lib_container_options.parseOptions(options.consumes, (item, key) => {
if (Array.isArray(item)) throw new Error("Unexpected array in options");
return item === key || !(0, _module_federation_sdk.isRequiredVersion)(item) ? {
import: key,
shareScope: options.shareScope || "default",
shareKey: key,
requiredVersion: void 0,
packageName: void 0,
strictVersion: false,
singleton: false,
eager: false,
issuerLayer: void 0,
layer: void 0,
request: key,
include: void 0,
exclude: void 0,
allowNodeModulesSuffixMatch: void 0,
treeShakingMode: void 0
} : {
import: key,
shareScope: options.shareScope || "default",
shareKey: key,
requiredVersion: item,
strictVersion: true,
packageName: void 0,
singleton: false,
eager: false,
issuerLayer: void 0,
layer: void 0,
request: key,
include: void 0,
exclude: void 0,
allowNodeModulesSuffixMatch: void 0,
treeShakingMode: void 0
};
}, (item, key) => {
const request = item.request || key;
return {
import: item.import === false ? void 0 : item.import || request,
shareScope: item.shareScope || options.shareScope || "default",
shareKey: item.shareKey || request,
requiredVersion: item.requiredVersion === false ? false : item.requiredVersion,
strictVersion: typeof item.strictVersion === "boolean" ? item.strictVersion : item.import !== false && !item.singleton,
packageName: item.packageName,
singleton: !!item.singleton,
eager: !!item.eager,
exclude: item.exclude,
include: item.include,
issuerLayer: item.issuerLayer ? item.issuerLayer : void 0,
layer: item.layer ? item.layer : void 0,
request,
allowNodeModulesSuffixMatch: item.allowNodeModulesSuffixMatch,
treeShakingMode: item.treeShakingMode
};
});
}
createConsumeSharedModule(compilation, context, request, config) {
const requiredVersionWarning = (details) => {
const error = new WebpackError(`No required version specified and unable to automatically determine one. ${details}`);
error.file = `shared module ${request}`;
compilation.warnings.push(error);
};
const directFallback = config.import && DIRECT_FALLBACK_REGEX.test(config.import);
const resolver = compilation.resolverFactory.get("normal", RESOLVE_OPTIONS);
return Promise.all([new Promise((resolve) => {
if (!config.import) return resolve(void 0);
const resolveContext = {
fileDependencies: new LazySet(),
contextDependencies: new LazySet(),
missingDependencies: new LazySet()
};
resolver.resolve({}, directFallback ? compilation.compiler.context : context, config.import, resolveContext, (err, result) => {
compilation.contextDependencies.addAll(resolveContext.contextDependencies);
compilation.fileDependencies.addAll(resolveContext.fileDependencies);
compilation.missingDependencies.addAll(resolveContext.missingDependencies);
if (err) {
compilation.errors.push(new ModuleNotFoundError(null, err, { name: `resolving fallback for shared module ${request}` }));
return resolve(void 0);
}
resolve(result);
});
}), new Promise((resolve) => {
if (config.requiredVersion !== void 0) return resolve(config.requiredVersion);
let packageName = config.packageName;
if (packageName === void 0) {
if (ABSOLUTE_PATH_REGEX.test(request)) return resolve(void 0);
const match = PACKAGE_NAME_REGEX.exec(request);
if (!match) {
requiredVersionWarning("Unable to extract the package name from request.");
return resolve(void 0);
}
packageName = match[0];
}
require_lib_sharing_utils.getDescriptionFile(compilation.inputFileSystem, context, ["package.json"], (err, result, checkedDescriptionFilePaths) => {
if (err) {
requiredVersionWarning(`Unable to read description file: ${err}`);
return resolve(void 0);
}
const { data } = result || {};
if (!data) {
if (checkedDescriptionFilePaths?.length) requiredVersionWarning([
`Unable to find required version for "${packageName}" in description file/s`,
checkedDescriptionFilePaths.join("\n"),
"It need to be in dependencies, devDependencies or peerDependencies."
].join("\n"));
else requiredVersionWarning(`Unable to find description file in ${context}.`);
return resolve(void 0);
}
if (data["name"] === packageName) return resolve(void 0);
resolve(require_lib_sharing_utils.getRequiredVersionFromDescriptionFile(data, packageName));
}, (result) => {
if (!result) return false;
const { data } = result;
const maybeRequiredVersion = require_lib_sharing_utils.getRequiredVersionFromDescriptionFile(data, packageName);
return data["name"] === packageName || typeof maybeRequiredVersion === "string";
});
})]).then(([importResolved, requiredVersion]) => {
const currentConfig = {
...config,
importResolved,
import: importResolved ? config.import : void 0,
requiredVersion
};
const consumedModule = new require_lib_sharing_ConsumeSharedModule.default(directFallback ? compilation.compiler.context : context, currentConfig);
if (config.include && typeof config.include.version === "string") {
if (!importResolved) return consumedModule;
return new Promise((resolveFilter) => {
require_lib_sharing_utils.getDescriptionFile(compilation.inputFileSystem, path.default.dirname(importResolved), ["package.json"], (err, result) => {
if (err) return resolveFilter(consumedModule);
const { data } = result || {};
if (!data || !data["version"] || data["name"] !== request) return resolveFilter(consumedModule);
if (config.include && satisfy(parseRange(config.include.version), data["version"])) {
if (config.include && config.include.version && config.singleton) require_lib_sharing_utils.addSingletonFilterWarning(compilation, config.shareKey || request, "include", "version", config.include.version, request, importResolved);
return resolveFilter(consumedModule);
}
if (config.include && typeof config.include.fallbackVersion === "string" && config.include.fallbackVersion) {
if (satisfy(parseRange(config.include.version), config.include.fallbackVersion)) return resolveFilter(consumedModule);
return resolveFilter(void 0);
}
return resolveFilter(void 0);
});
});
}
if (config.exclude && typeof config.exclude.version === "string") {
if (!importResolved) return consumedModule;
if (config.exclude && typeof config.exclude.fallbackVersion === "string" && config.exclude.fallbackVersion) {
if (satisfy(parseRange(config.exclude.version), config.exclude.fallbackVersion)) return;
return consumedModule;
}
return new Promise((resolveFilter) => {
require_lib_sharing_utils.getDescriptionFile(compilation.inputFileSystem, path.default.dirname(importResolved), ["package.json"], (err, result) => {
if (err) return resolveFilter(consumedModule);
const { data } = result || {};
if (!data || !data["version"] || data["name"] !== request) return resolveFilter(consumedModule);
if (config.exclude && typeof config.exclude.version === "string" && satisfy(parseRange(config.exclude.version), data["version"])) return resolveFilter(void 0);
if (config.exclude && config.exclude.version && config.singleton) require_lib_sharing_utils.addSingletonFilterWarning(compilation, config.shareKey || request, "exclude", "version", config.exclude.version, request, importResolved);
return resolveFilter(consumedModule);
});
});
}
return consumedModule;
});
}
apply(compiler) {
new require_lib_container_runtime_FederationRuntimePlugin.default().apply(compiler);
process.env["FEDERATION_WEBPACK_PATH"] = process.env["FEDERATION_WEBPACK_PATH"] || (0, _module_federation_sdk_normalize_webpack_path.getWebpackPath)(compiler);
compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation, { normalModuleFactory }) => {
compilation.dependencyFactories.set(require_lib_sharing_ConsumeSharedFallbackDependency.default, normalModuleFactory);
let unresolvedConsumes, resolvedConsumes, prefixedConsumes;
const promise = require_lib_sharing_resolveMatchedConfigs.resolveMatchedConfigs(compilation, this._consumes).then(({ resolved, unresolved, prefixed }) => {
resolvedConsumes = resolved;
unresolvedConsumes = unresolved;
prefixedConsumes = prefixed;
});
normalModuleFactory.hooks.factorize.tapPromise(PLUGIN_NAME, async (resolveData) => {
const { context, request, dependencies, contextInfo } = resolveData;
const boundCreateConsumeSharedModule = this.createConsumeSharedModule.bind(this);
return promise.then(() => {
if (dependencies[0] instanceof require_lib_sharing_ConsumeSharedFallbackDependency.default || dependencies[0] instanceof require_lib_sharing_ProvideForSharedDependency.default) return;
const { context, request, contextInfo } = resolveData;
const match = unresolvedConsumes.get(require_lib_sharing_utils.createLookupKeyForSharing(request, contextInfo.issuerLayer)) || unresolvedConsumes.get(require_lib_sharing_utils.createLookupKeyForSharing(request, void 0));
if (match !== void 0) return boundCreateConsumeSharedModule(compilation, context, request, match);
let reconstructed = null;
let modulePathAfterNodeModules = null;
if (request && !path.default.isAbsolute(request) && RELATIVE_OR_ABSOLUTE_PATH_REGEX.test(request)) {
reconstructed = path.default.join(context, request);
modulePathAfterNodeModules = require_lib_sharing_utils.extractPathAfterNodeModules(reconstructed);
if (modulePathAfterNodeModules) {
const moduleMatch = unresolvedConsumes.get(require_lib_sharing_utils.createLookupKeyForSharing(modulePathAfterNodeModules, contextInfo.issuerLayer)) || unresolvedConsumes.get(require_lib_sharing_utils.createLookupKeyForSharing(modulePathAfterNodeModules, void 0));
if (moduleMatch !== void 0 && moduleMatch.allowNodeModulesSuffixMatch) return boundCreateConsumeSharedModule(compilation, context, modulePathAfterNodeModules, moduleMatch);
}
const reconstructedMatch = unresolvedConsumes.get(require_lib_sharing_utils.createLookupKeyForSharing(reconstructed, contextInfo.issuerLayer)) || unresolvedConsumes.get(require_lib_sharing_utils.createLookupKeyForSharing(reconstructed, void 0));
if (reconstructedMatch !== void 0) return boundCreateConsumeSharedModule(compilation, context, reconstructed, reconstructedMatch);
}
for (const [prefix, options] of prefixedConsumes) {
const lookup = options.request || prefix;
if (options.issuerLayer) {
if (!contextInfo.issuerLayer) continue;
if (contextInfo.issuerLayer !== options.issuerLayer) continue;
}
if (request.startsWith(lookup)) {
const remainder = request.slice(lookup.length);
if (!require_lib_sharing_utils.testRequestFilters(remainder, options.include?.request, options.exclude?.request)) continue;
return boundCreateConsumeSharedModule(compilation, context, request, {
...options,
import: options.import ? options.import + remainder : void 0,
shareKey: options.shareKey + remainder,
layer: options.layer
});
}
}
if (modulePathAfterNodeModules) for (const [prefix, options] of prefixedConsumes) {
if (!options.allowNodeModulesSuffixMatch) continue;
if (options.issuerLayer) {
if (!contextInfo.issuerLayer) continue;
if (contextInfo.issuerLayer !== options.issuerLayer) continue;
}
const lookup = options.request || prefix;
if (modulePathAfterNodeModules.startsWith(lookup)) {
const remainder = modulePathAfterNodeModules.slice(lookup.length);
if (!require_lib_sharing_utils.testRequestFilters(remainder, options.include?.request, options.exclude?.request)) continue;
return boundCreateConsumeSharedModule(compilation, context, modulePathAfterNodeModules, {
...options,
import: options.import ? options.import + remainder : void 0,
shareKey: options.shareKey + remainder,
layer: options.layer
});
}
}
});
});
normalModuleFactory.hooks.createModule.tapPromise(PLUGIN_NAME, ({ resource }, { context, dependencies }) => {
const boundCreateConsumeSharedModule = this.createConsumeSharedModule.bind(this);
if (dependencies[0] instanceof require_lib_sharing_ConsumeSharedFallbackDependency.default || dependencies[0] instanceof require_lib_sharing_ProvideForSharedDependency.default) return Promise.resolve();
if (resource) {
const options = resolvedConsumes.get(resource);
if (options !== void 0) return boundCreateConsumeSharedModule(compilation, context, resource, options);
}
return Promise.resolve();
});
compilation.hooks.finishModules.tapAsync({
name: PLUGIN_NAME,
stage: 10
}, (modules, callback) => {
for (const module of modules) {
if (!(module instanceof require_lib_sharing_ConsumeSharedModule.default) || !module.options.import) continue;
let dependency;
if (module.options.eager) dependency = module.dependencies[0];
else dependency = module.blocks[0]?.dependencies[0];
if (dependency) {
const fallbackModule = compilation.moduleGraph.getModule(dependency);
if (fallbackModule && fallbackModule.buildMeta && fallbackModule.buildInfo) {
module.buildMeta = { ...fallbackModule.buildMeta };
module.buildInfo = { ...fallbackModule.buildInfo };
compilation.moduleGraph.getExportsInfo(module).setUnknownExportsProvided();
}
}
}
callback();
});
compilation.hooks.additionalTreeRuntimeRequirements.tap(PLUGIN_NAME, (chunk, set) => {
set.add(RuntimeGlobals.module);
set.add(RuntimeGlobals.moduleCache);
set.add(RuntimeGlobals.moduleFactoriesAddOnly);
set.add(RuntimeGlobals.shareScopeMap);
set.add(RuntimeGlobals.initializeSharing);
set.add(RuntimeGlobals.hasOwnProperty);
compilation.addRuntimeModule(chunk, new require_lib_sharing_ConsumeSharedRuntimeModule.default(set));
compilation.addRuntimeModule(chunk, new require_lib_sharing_ShareRuntimeModule.default());
});
});
}
};
//#endregion
exports.default = ConsumeSharedPlugin;
//# sourceMappingURL=ConsumeSharedPlugin.js.map