UNPKG

@module-federation/manifest

Version:

Provide manifest/stats for webpack/rspack MF project .

513 lines (502 loc) • 20 kB
"use strict"; const __rslib_import_meta_url__ = /*#__PURE__*/ (function () { return typeof document === 'undefined' ? new (require('url'.replace('', '')).URL)('file:' + __filename).href : (document.currentScript && document.currentScript.src) || new URL('main.js', document.baseURI).href; })(); ; // The require scope var __webpack_require__ = {}; /************************************************************************/ // webpack/runtime/compat_get_default_export (() => { // getDefaultExport function for compatibility with non-ESM modules __webpack_require__.n = (module) => { var getter = module && module.__esModule ? () => (module['default']) : () => (module); __webpack_require__.d(getter, { a: getter }); return getter; }; })(); // webpack/runtime/define_property_getters (() => { __webpack_require__.d = (exports, definition) => { for(var key in definition) { if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); } } }; })(); // webpack/runtime/has_own_property (() => { __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) })(); // webpack/runtime/make_namespace_object (() => { // define __esModule on exports __webpack_require__.r = (exports) => { if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); } Object.defineProperty(exports, '__esModule', { value: true }); }; })(); /************************************************************************/ var __webpack_exports__ = {}; // ESM COMPAT FLAG __webpack_require__.r(__webpack_exports__); // EXPORTS __webpack_require__.d(__webpack_exports__, { getExposeItem: () => (/* binding */ getExposeItem), ModuleHandler: () => (/* binding */ ModuleHandler), getShareItem: () => (/* binding */ getShareItem), getExposeName: () => (/* binding */ getExposeName) }); ;// CONCATENATED MODULE: external "@module-federation/sdk" const sdk_namespaceObject = require("@module-federation/sdk"); ;// CONCATENATED MODULE: external "path" const external_path_namespaceObject = require("path"); var external_path_default = /*#__PURE__*/__webpack_require__.n(external_path_namespaceObject); ;// CONCATENATED MODULE: external "@module-federation/managers" const managers_namespaceObject = require("@module-federation/managers"); ;// CONCATENATED MODULE: external "./utils.js" const external_utils_js_namespaceObject = require("./utils.js"); ;// CONCATENATED MODULE: ./src/ModuleHandler.ts const isNonEmptyString = (value)=>{ return typeof value === 'string' && value.trim().length > 0; }; const normalizeExposeValue = (exposeValue)=>{ if (!exposeValue) { return undefined; } const toImportArray = (value)=>{ if (isNonEmptyString(value)) { return [ value ]; } if (Array.isArray(value)) { const normalized = value.filter(isNonEmptyString); return normalized.length ? normalized : undefined; } return undefined; }; if (typeof exposeValue === 'object') { if ('import' in exposeValue) { const { import: rawImport, name } = exposeValue; const normalizedImport = toImportArray(rawImport); if (!(normalizedImport === null || normalizedImport === void 0 ? void 0 : normalizedImport.length)) { return undefined; } return { import: normalizedImport, ...isNonEmptyString(name) ? { name } : {} }; } return undefined; } const normalizedImport = toImportArray(exposeValue); if (!(normalizedImport === null || normalizedImport === void 0 ? void 0 : normalizedImport.length)) { return undefined; } return { import: normalizedImport }; }; const parseContainerExposeEntries = (identifier)=>{ const startIndex = identifier.indexOf('['); if (startIndex < 0) { return undefined; } let depth = 0; let inString = false; let isEscaped = false; for(let cursor = startIndex; cursor < identifier.length; cursor++){ const char = identifier[cursor]; if (isEscaped) { isEscaped = false; continue; } if (char === '\\') { isEscaped = true; continue; } if (char === '"') { inString = !inString; continue; } if (inString) { continue; } if (char === '[') { depth++; } else if (char === ']') { depth--; if (depth === 0) { const serialized = identifier.slice(startIndex, cursor + 1); try { return JSON.parse(serialized); } catch { return undefined; } } } } return undefined; }; const getExposeName = (exposeKey)=>{ return exposeKey.replace('./', ''); }; function getExposeItem({ exposeKey, name, file }) { const exposeModuleName = getExposeName(exposeKey); return { path: exposeKey, id: (0,sdk_namespaceObject.composeKeyWithSeparator)(name, exposeModuleName), name: exposeModuleName, // @ts-ignore to deduplicate requires: [], file: external_path_default().relative(process.cwd(), file.import[0]), assets: { js: { async: [], sync: [] }, css: { async: [], sync: [] } } }; } const getShareItem = ({ pkgName, normalizedShareOptions, pkgVersion, hostName })=>{ return { ...normalizedShareOptions, id: `${hostName}:${pkgName}`, requiredVersion: (normalizedShareOptions === null || normalizedShareOptions === void 0 ? void 0 : normalizedShareOptions.requiredVersion) || `^${pkgVersion}`, name: pkgName, version: pkgVersion, assets: { js: { async: [], sync: [] }, css: { async: [], sync: [] } }, // @ts-ignore to deduplicate usedIn: new Set(), usedExports: [], fallback: '' }; }; class ModuleHandler { get isRspack() { return this._bundler === 'rspack'; } _handleSharedModule(mod, sharedMap, exposesMap) { const { identifier, moduleType } = mod; if (!identifier) { return; } const sharedManagerNormalizedOptions = this._sharedManager.normalizedOptions; const initShared = (pkgName, pkgVersion)=>{ if (sharedMap[pkgName]) { return; } sharedMap[pkgName] = getShareItem({ pkgName, pkgVersion, normalizedShareOptions: sharedManagerNormalizedOptions[pkgName], hostName: this._options.name }); }; const collectRelationshipMap = (mod, pkgName)=>{ const { issuerName, reasons } = mod; if (issuerName) { if (exposesMap[(0,external_utils_js_namespaceObject.getFileNameWithOutExt)(issuerName)]) { const expose = exposesMap[(0,external_utils_js_namespaceObject.getFileNameWithOutExt)(issuerName)]; // @ts-ignore use Set to deduplicate expose.requires.push(pkgName); // @ts-ignore use Set to deduplicate sharedMap[pkgName].usedIn.add(expose.path); } } if (reasons) { reasons.forEach(({ resolvedModule, moduleName })=>{ let exposeModName = this.isRspack ? moduleName : resolvedModule; // filters out entrypoints if (exposeModName) { if (exposesMap[(0,external_utils_js_namespaceObject.getFileNameWithOutExt)(exposeModName)]) { const expose = exposesMap[(0,external_utils_js_namespaceObject.getFileNameWithOutExt)(exposeModName)]; // @ts-ignore to deduplicate expose.requires.push(pkgName); // @ts-ignore to deduplicate sharedMap[pkgName].usedIn.add(expose.path); } } }); } }; const parseResolvedIdentifier = (nameAndVersion)=>{ let name = ''; let version = ''; if (nameAndVersion.startsWith('@')) { const splitInfo = nameAndVersion.split('@'); splitInfo[0] = '@'; name = splitInfo[0] + splitInfo[1]; version = splitInfo[2]; } else if (nameAndVersion.includes('@')) { [name, version] = nameAndVersion.split('@'); version = version.replace(/[\^~>|>=]/g, ''); } return { name, version }; }; if (moduleType === 'provide-module') { // identifier(rspack) = provide shared module (default) react@18.2.0 = /temp/node_modules/.pnpm/react@18.2.0/node_modules/react/index.js // identifier(webpack) = provide module (default) react@18.2.0 = /temp/node_modules/.pnpm/react@18.2.0/node_modules/react/index.js const data = identifier.split(' '); const nameAndVersion = this.isRspack ? data[4] : data[3]; const { name, version } = parseResolvedIdentifier(nameAndVersion); if (name && version) { initShared(name, version); collectRelationshipMap(mod, name); } } if (moduleType === 'consume-shared-module') { // identifier(rspack) = consume shared module (default) lodash/get@^4.17.21 (strict) (fallback: /temp/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/get.js) // identifier(webpack) = consume-shared-module|default|react-dom|!=1.8...2...0|false|/temp/node_modules/.pnpm/react-dom@18.2.0_react@18.2.0/node_modules/react-dom/index.js|true|false const SEPARATOR = this.isRspack ? ' ' : '|'; const data = identifier.split(SEPARATOR); let pkgName = ''; let pkgVersion = ''; if (this.isRspack) { const nameAndVersion = data[4]; const res = parseResolvedIdentifier(nameAndVersion); pkgName = res.name; pkgVersion = res.version; } else { pkgName = data[2]; const pkgVersionRange = data[3]; pkgVersion = ''; if (pkgVersionRange.startsWith('=')) { pkgVersion = data[3].replace('=', ''); } else { if (sharedManagerNormalizedOptions[pkgName]) { pkgVersion = sharedManagerNormalizedOptions[pkgName].version; } else { const fullPkgName = pkgName.split('/').slice(0, -1).join('/'); // pkgName: react-dom/ if (sharedManagerNormalizedOptions[`${fullPkgName}/`]) { if (sharedManagerNormalizedOptions[fullPkgName]) { pkgVersion = sharedManagerNormalizedOptions[fullPkgName].version; } else { pkgVersion = sharedManagerNormalizedOptions[`${fullPkgName}/`].version; } } } } } if (pkgName && pkgVersion) { initShared(pkgName, pkgVersion); collectRelationshipMap(mod, pkgName); } } } _handleRemoteModule(mod, remotes, remotesConsumerMap) { const { identifier, reasons, nameForCondition } = mod; if (!identifier) { return; } const remoteManagerNormalizedOptions = this._remoteManager.normalizedOptions; // identifier = remote (default) webpack/container/reference/app2 ./Button const data = identifier.split(' '); if (data.length === 4) { const moduleName = data[3].replace('./', ''); const remoteAlias = data[2].replace('webpack/container/reference/', ''); const normalizedRemote = remoteManagerNormalizedOptions[remoteAlias]; const basicRemote = { alias: normalizedRemote.alias, consumingFederationContainerName: this._options.name || '', federationContainerName: remoteManagerNormalizedOptions[remoteAlias].name, moduleName, // @ts-ignore to deduplicate usedIn: new Set() }; if (!nameForCondition) { return; } let remote; if ('version' in normalizedRemote) { remote = { ...basicRemote, version: normalizedRemote.version }; } else { remote = { ...basicRemote, entry: normalizedRemote.entry }; } remotes.push(remote); remotesConsumerMap[nameForCondition] = remote; } if (reasons) { reasons.forEach(({ userRequest, resolvedModule, moduleName })=>{ let exposeModName = this.isRspack ? moduleName : resolvedModule; if (userRequest && exposeModName && remotesConsumerMap[userRequest]) { // @ts-ignore to deduplicate remotesConsumerMap[userRequest].usedIn.add(exposeModName.replace('./', '')); } }); } } _handleContainerModule(mod, exposesMap) { const { identifier } = mod; if (!identifier) { return; } // identifier: container entry (default) [[".",{"import":["./src/routes/page.tsx"],"name":"__federation_expose_default_export"}]]' const entries = parseContainerExposeEntries(identifier) ?? this._getContainerExposeEntriesFromOptions(); if (!entries) { return; } entries.forEach(([prefixedName, file])=>{ // TODO: support multiple import exposesMap[(0,external_utils_js_namespaceObject.getFileNameWithOutExt)(file.import[0])] = getExposeItem({ exposeKey: prefixedName, name: this._options.name, file }); }); } _getContainerExposeEntriesFromOptions() { const exposes = this._containerManager.containerPluginExposesOptions; const normalizedEntries = Object.entries(exposes).reduce((acc, [exposeKey, exposeOptions])=>{ const normalizedExpose = normalizeExposeValue(exposeOptions); if (!(normalizedExpose === null || normalizedExpose === void 0 ? void 0 : normalizedExpose.import.length)) { return acc; } acc.push([ exposeKey, normalizedExpose ]); return acc; }, []); if (normalizedEntries.length) { return normalizedEntries; } const rawExposes = this._options.exposes; if (!rawExposes || Array.isArray(rawExposes)) { return undefined; } const normalizedFromOptions = Object.entries(rawExposes).reduce((acc, [exposeKey, exposeOptions])=>{ const normalizedExpose = normalizeExposeValue(exposeOptions); if (!(normalizedExpose === null || normalizedExpose === void 0 ? void 0 : normalizedExpose.import.length)) { return acc; } acc.push([ exposeKey, normalizedExpose ]); return acc; }, []); return normalizedFromOptions.length ? normalizedFromOptions : undefined; } _initializeExposesFromOptions(exposesMap) { if (!this._options.name || !this._containerManager.enable) { return; } const exposes = this._containerManager.containerPluginExposesOptions; Object.entries(exposes).forEach(([exposeKey, exposeOptions])=>{ var _exposeOptions_import; if (!((_exposeOptions_import = exposeOptions.import) === null || _exposeOptions_import === void 0 ? void 0 : _exposeOptions_import.length)) { return; } const [exposeImport] = exposeOptions.import; if (!exposeImport) { return; } const exposeMapKey = (0,external_utils_js_namespaceObject.getFileNameWithOutExt)(exposeImport); if (!exposesMap[exposeMapKey]) { exposesMap[exposeMapKey] = getExposeItem({ exposeKey, name: this._options.name, file: exposeOptions }); } }); } collect() { const remotes = []; const remotesConsumerMap = {}; const exposesMap = {}; const sharedMap = {}; this._initializeExposesFromOptions(exposesMap); const isSharedModule = (moduleType)=>{ return Boolean(moduleType && [ 'provide-module', 'consume-shared-module' ].includes(moduleType)); }; const isContainerModule = (identifier)=>{ return identifier.startsWith('container entry'); }; const isRemoteModule = (identifier)=>{ return identifier.startsWith('remote '); }; // handle remote/expose this._modules.forEach((mod)=>{ const { identifier, reasons, nameForCondition, moduleType } = mod; if (!identifier) { return; } if (isSharedModule(moduleType)) { this._handleSharedModule(mod, sharedMap, exposesMap); } if (isRemoteModule(identifier)) { this._handleRemoteModule(mod, remotes, remotesConsumerMap); } else if (isContainerModule(identifier)) { this._handleContainerModule(mod, exposesMap); } }); return { remotes, exposesMap, sharedMap }; } constructor(options, modules, { bundler }){ this._bundler = 'webpack'; this._remoteManager = new managers_namespaceObject.RemoteManager(); this._sharedManager = new managers_namespaceObject.SharedManager(); this._options = options; this._modules = modules; this._bundler = bundler; this._containerManager = new managers_namespaceObject.ContainerManager(); this._containerManager.init(options); this._remoteManager = new managers_namespaceObject.RemoteManager(); this._remoteManager.init(options); this._sharedManager = new managers_namespaceObject.SharedManager(); this._sharedManager.init(options); } } exports.ModuleHandler = __webpack_exports__.ModuleHandler; exports.getExposeItem = __webpack_exports__.getExposeItem; exports.getExposeName = __webpack_exports__.getExposeName; exports.getShareItem = __webpack_exports__.getShareItem; for(var __webpack_i__ in __webpack_exports__) { if(["ModuleHandler","getExposeItem","getExposeName","getShareItem"].indexOf(__webpack_i__) === -1) { exports[__webpack_i__] = __webpack_exports__[__webpack_i__]; } } Object.defineProperty(exports, '__esModule', { value: true });