UNPKG

@module-federation/vite

Version:
1,251 lines (1,230 loc) 62.7 kB
var defu = require('defu'); var fs = require('fs'); var path = require('pathe'); var pluginutils = require('@rollup/pluginutils'); var estreeWalker = require('estree-walker'); var MagicString = require('magic-string'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } function _interopNamespace(e) { if (e && e.__esModule) return e; var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n["default"] = e; return n; } var defu__default = /*#__PURE__*/_interopDefaultLegacy(defu); var fs__namespace = /*#__PURE__*/_interopNamespace(fs); var path__namespace = /*#__PURE__*/_interopNamespace(path); var path__default = /*#__PURE__*/_interopDefaultLegacy(path); var MagicString__default = /*#__PURE__*/_interopDefaultLegacy(MagicString); function getFirstHtmlEntryFile(entryFiles) { return entryFiles.find(function (file) { return file.endsWith('.html'); }); } var addEntry = function addEntry(_ref) { var entryName = _ref.entryName, entryPath = _ref.entryPath, fileName = _ref.fileName, _ref$inject = _ref.inject, inject = _ref$inject === void 0 ? 'entry' : _ref$inject; var devEntryPath = entryPath.startsWith('virtual:mf') ? '@id/' + entryPath : entryPath; var entryFiles = []; var htmlFilePath; var _command; var emitFileId; var viteConfig; function injectHtml() { return inject === 'html' && htmlFilePath; } function injectEntry() { return inject === 'entry' || !htmlFilePath; } return [{ name: 'add-entry', apply: 'serve', config: function config(_config, _ref2) { var command = _ref2.command; _command = command; }, configResolved: function configResolved(config) { viteConfig = config; devEntryPath = config.base + devEntryPath.replace(/\\\\?/g, '/').replace(/.+?\:([/\\])[/\\]?/, '$1').replace(/^\//, ''); }, configureServer: function configureServer(server) { server.middlewares.use(function (req, res, next) { if (!fileName) { next(); return; } if (req.url && req.url.startsWith((viteConfig.base + fileName).replace(/^\/?/, '/'))) { req.url = devEntryPath; } next(); }); }, transformIndexHtml: function transformIndexHtml(c) { if (!injectHtml()) return; return c.replace('<head>', "<head><script type=\"module\" src=" + JSON.stringify(devEntryPath.replace(/.+?\:([/\\])[/\\]?/, '$1').replace(/\\\\?/g, '/')) + "></script>"); }, transform: function transform(code, id) { if (id.includes('node_modules') || inject !== 'html' || htmlFilePath) { return; } if (id.includes('.svelte-kit') && id.includes('internal.js')) { var src = devEntryPath.replace(/.+?\:([/\\])[/\\]?/, '$1').replace(/\\\\?/g, '/'); return code.replace(/<head>/g, '<head><script type=\\"module\\" src=\\"' + src + '\\"></script>'); } } }, { name: 'add-entry', enforce: 'post', configResolved: function configResolved(config) { viteConfig = config; var inputOptions = config.build.rollupOptions.input; if (!inputOptions) { htmlFilePath = path__namespace.resolve(config.root, 'index.html'); } else if (typeof inputOptions === 'string') { entryFiles = [inputOptions]; } else if (Array.isArray(inputOptions)) { entryFiles = inputOptions; } else if (typeof inputOptions === 'object') { entryFiles = Object.values(inputOptions); } if (entryFiles && entryFiles.length > 0) { htmlFilePath = getFirstHtmlEntryFile(entryFiles); } }, buildStart: function buildStart() { if (_command === 'serve') return; var hasHash = fileName == null || fileName.includes == null ? void 0 : fileName.includes('[hash'); var emitFileOptions = { name: entryName, type: 'chunk', id: entryPath, preserveSignature: 'strict' }; if (!hasHash) { emitFileOptions.fileName = fileName; } emitFileId = this.emitFile(emitFileOptions); if (htmlFilePath && fs__namespace.existsSync(htmlFilePath)) { var htmlContent = fs__namespace.readFileSync(htmlFilePath, 'utf-8'); var scriptRegex = /<script\s+[^>]*src=["']([^"']+)["'][^>]*>/gi; var match; while ((match = scriptRegex.exec(htmlContent)) !== null) { entryFiles.push(match[1]); } } }, generateBundle: function generateBundle(options, bundle) { if (!injectHtml()) return; var file = this.getFileName(emitFileId); var scriptContent = "\n <script type=\"module\" src=\"" + (viteConfig.base + file) + "\"></script>\n "; for (var _fileName in bundle) { if (_fileName.endsWith('.html')) { var htmlAsset = bundle[_fileName]; if (htmlAsset.type === 'chunk') return; var htmlContent = htmlAsset.source.toString() || ''; htmlContent = htmlContent.replace('<head>', "<head>" + scriptContent); htmlAsset.source = htmlContent; } } }, transform: function transform(code, id) { if (injectEntry() && entryFiles.some(function (file) { return id.endsWith(file); })) { var injection = "\n import " + JSON.stringify(entryPath) + ";\n "; return injection + code; } } }]; }; /** * Solve the problem that dev mode dependency prebunding does not support top-level await syntax */ function PluginDevProxyModuleTopLevelAwait() { var filterFunction = pluginutils.createFilter(); var processedFlag = '/* already-processed-by-dev-proxy-module-top-level-await */'; return { name: 'dev-proxy-module-top-level-await', apply: 'serve', transform: function transform(code, id) { if (code.includes(processedFlag)) { return null; } if (!code.includes('/*mf top-level-await placeholder replacement mf*/')) { return null; } if (!filterFunction(id)) return null; var ast; try { ast = this.parse(code, { allowReturnOutsideFunction: true }); } catch (e) { throw new Error(id + ": " + e); } var magicString = new MagicString__default["default"](code); estreeWalker.walk(ast, { enter: function enter(node) { if (node.type === 'ExportNamedDeclaration' && node.specifiers) { var exportSpecifiers = node.specifiers.map(function (specifier) { return specifier.exported.name; }); var proxyStatements = exportSpecifiers.map(function (name) { return "\n const __mfproxy__await" + name + " = await " + name + "();\n const __mfproxy__" + name + " = () => __mfproxy__await" + name + ";\n "; }).join('\n'); var exportStatements = exportSpecifiers.map(function (name) { return "__mfproxy__" + name + " as " + name; }).join(', '); var start = node.start; var end = node.end; var replacement = proxyStatements + "\nexport { " + exportStatements + " };"; magicString.overwrite(start, end, replacement); } if (node.type === 'ExportDefaultDeclaration') { var declaration = node.declaration; var _start = node.start; var _end = node.end; var proxyStatement; var exportStatement = 'default'; if (declaration.type === 'Identifier') { // example: export default foo; proxyStatement = "\n const __mfproxy__awaitdefault = await " + declaration.name + "();\n const __mfproxy__default = __mfproxy__awaitdefault;\n "; } else if (declaration.type === 'CallExpression' || declaration.type === 'FunctionDeclaration') { // example: export default someFunction(); var declarationCode = code.slice(declaration.start, declaration.end); proxyStatement = "\n const __mfproxy__awaitdefault = await (" + declarationCode + ");\n const __mfproxy__default = __mfproxy__awaitdefault;\n "; } else { // other proxyStatement = "\n const __mfproxy__awaitdefault = await (" + code.slice(declaration.start, declaration.end) + ");\n const __mfproxy__default = __mfproxy__awaitdefault;\n "; } var _replacement = proxyStatement + "\nexport { __mfproxy__default as " + exportStatement + " };"; magicString.overwrite(_start, _end, _replacement); } } }); var transformedCode = magicString.toString(); return { code: processedFlag + "\n" + transformedCode, map: magicString.generateMap({ hires: true }) }; } }; } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } function _createForOfIteratorHelperLoose(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (t) return (t = t.call(r)).next.bind(t); if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var o = 0; return function () { return o >= r.length ? { done: !0 } : { done: !1, value: r[o++] }; }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } var warn = function warn(message) { return message.split('\n').forEach(function (msg) { return console.warn('\x1b[33m%s\x1b[0m', msg); }); }; function normalizeExposesItem(key, item) { var importPath = ''; if (typeof item === 'string') { importPath = item; } if (typeof item === 'object') { importPath = item["import"]; } return { "import": importPath }; } function normalizeExposes(exposes) { if (!exposes) return {}; var res = {}; Object.keys(exposes).forEach(function (key) { res[key] = normalizeExposesItem(key, exposes[key]); }); return res; } function normalizeRemotes(remotes) { if (!remotes) return {}; var result = {}; if (typeof remotes === 'object') { Object.keys(remotes).forEach(function (key) { result[key] = normalizeRemoteItem(key, remotes[key]); }); } return result; } function normalizeRemoteItem(key, remote) { if (typeof remote === 'string') { var _remote$split = remote.split('@'), entryGlobalName = _remote$split[0]; var entry = remote.replace(entryGlobalName + '@', ''); return { type: 'var', name: key, entry: entry, entryGlobalName: entryGlobalName, shareScope: 'default' }; } return Object.assign({ type: 'var', name: key, shareScope: 'default', entryGlobalName: key }, remote); } function removePathFromNpmPackage(packageString) { // 匹配npm包名的正则表达式,忽略路径部分 var regex = /^(?:@[^/]+\/)?[^/]+/; // 使用正则表达式匹配并提取包名 var match = packageString.match(regex); // 返回匹配到的包名,如果没有匹配到则返回原字符串 return match ? match[0] : packageString; } /** * Tries to find the package.json's version of a shared package * if `package.json` is not declared in `exports` * @param {string} sharedName * @returns {string | undefined} */ function searchPackageVersion(sharedName) { try { var sharedPath = require.resolve(sharedName); var potentialPackageJsonDir = path__namespace.dirname(sharedPath); var rootDir = path__namespace.parse(potentialPackageJsonDir).root; while (path__namespace.parse(potentialPackageJsonDir).base !== 'node_modules' && potentialPackageJsonDir !== rootDir) { var potentialPackageJsonPath = path__namespace.join(potentialPackageJsonDir, 'package.json'); if (fs__namespace.existsSync(potentialPackageJsonPath)) { var potentialPackageJson = require(potentialPackageJsonPath); if (typeof potentialPackageJson == 'object' && potentialPackageJson !== null && typeof potentialPackageJson.version === 'string' && potentialPackageJson.name === sharedName) { return potentialPackageJson.version; } } potentialPackageJsonDir = path__namespace.dirname(potentialPackageJsonDir); } } catch (_) {} return undefined; } function normalizeShareItem(key, shareItem) { var version; try { try { version = require(path__namespace.join(removePathFromNpmPackage(key), 'package.json')).version; } catch (e1) { try { var localPath = path__namespace.join(process.cwd(), 'node_modules', removePathFromNpmPackage(key), 'package.json'); version = require(localPath).version; } catch (e2) { version = searchPackageVersion(key); if (!version) console.error(e1); } } } catch (e) { console.error("Unexpected error resolving version for " + key + ":", e); } if (typeof shareItem === 'string') { return { name: shareItem, version: version, scope: 'default', from: '', shareConfig: { singleton: false, requiredVersion: version ? "^" + version : '*' } }; } return { name: key, from: '', version: shareItem.version || version, scope: shareItem.shareScope || 'default', shareConfig: { singleton: shareItem.singleton || false, requiredVersion: shareItem.requiredVersion || (version ? "^" + version : '*'), strictVersion: !!shareItem.strictVersion } }; } function normalizeShared(shared) { if (!shared) return {}; var result = {}; if (Array.isArray(shared)) { shared.forEach(function (key) { result[key] = normalizeShareItem(key, key); }); return result; } if (typeof shared === 'object') { Object.keys(shared).forEach(function (key) { result[key] = normalizeShareItem(key, shared[key]); }); } return result; } function normalizeLibrary(library) { if (!library) return undefined; return library; } function normalizeManifest(manifest) { if (manifest === void 0) { manifest = false; } if (typeof manifest === 'boolean') { return manifest; } return Object.assign({ filePath: '', disableAssetsAnalyze: false, fileName: 'mf-manifest.json' }, manifest); } var config; function getNormalizeModuleFederationOptions() { return config; } function getNormalizeShareItem(key) { var options = getNormalizeModuleFederationOptions(); var shareItem = options.shared[key] || options.shared[removePathFromNpmPackage(key)] || options.shared[removePathFromNpmPackage(key) + '/']; return shareItem; } function normalizeModuleFederationOptions(options) { if (options.getPublicPath) { warn("We are ignoring the getPublicPath options because they are natively supported by Vite\nwith the \"experimental.renderBuiltUrl\" configuration https://vitejs.dev/guide/build#advanced-base-options"); } if (options.virtualModuleDir && options.virtualModuleDir.includes('/')) { throw new Error("Invalid virtualModuleDir: \"" + options.virtualModuleDir + "\". " + "The virtualModuleDir option cannot contain slashes (/). " + "Please use a single directory name like '__mf__virtual__your_app_name'."); } return config = { exposes: normalizeExposes(options.exposes), filename: options.filename || 'remoteEntry-[hash]', library: normalizeLibrary(options.library), name: options.name, // remoteType: options.remoteType, remotes: normalizeRemotes(options.remotes), runtime: options.runtime, shareScope: options.shareScope || 'default', shared: normalizeShared(options.shared), runtimePlugins: options.runtimePlugins || [], implementation: options.implementation || require.resolve('@module-federation/runtime'), manifest: normalizeManifest(options.manifest), dev: options.dev, dts: options.dts, getPublicPath: options.getPublicPath, publicPath: options.publicPath, shareStrategy: options.shareStrategy || 'version-first', ignoreOrigin: options.ignoreOrigin || false, virtualModuleDir: options.virtualModuleDir || '__mf__virtual' }; } /** * Escaping rules: * Convert using the format __${mapping}__, where _ and $ are not allowed in npm package names but can be used in variable names. * @ => 1 * / => 2 * - => 3 * . => 4 */ /** * Encodes a package name into a valid file name. * @param {string} name - The package name, e.g., "@scope/xx-xx.xx". * @returns {string} - The encoded file name. */ function packageNameEncode(name) { if (typeof name !== 'string') throw new Error('A string package name is required'); return name.replace(/@/g, '_mf_0_').replace(/\//g, '_mf_1_').replace(/-/g, '_mf_2_').replace(/\./g, '_mf_3_'); } /** * Decodes an encoded file name back to the original package name. * @param {string} encoded - The encoded file name, e.g., "_mf_0_scope_mf_1_xx_mf_2_xx_mf_3_xx". * @returns {string} - The decoded package name. */ function packageNameDecode(encoded) { if (typeof encoded !== 'string') throw new Error('A string encoded file name is required'); return encoded.replace(/_mf_0_/g, '@').replace(/_mf_1_/g, '/').replace(/_mf_2_/g, '-').replace(/_mf_3_/g, '.'); } /** * https://github.com/module-federation/vite/issues/68 */ function getLocalSharedImportMapPath_temp() { var _getNormalizeModuleFe = getNormalizeModuleFederationOptions(), name = _getNormalizeModuleFe.name; return path__default["default"].resolve('.__mf__temp', packageNameEncode(name), 'localSharedImportMap'); } function writeLocalSharedImportMap_temp(content) { var localSharedImportMapId = getLocalSharedImportMapPath_temp(); createFile(localSharedImportMapId + '.js', '\n// Windows temporarily needs this file, https://github.com/module-federation/vite/issues/68\n' + content); } function createFile(filePath, content) { var dir = path__default["default"].dirname(filePath); fs.mkdirSync(dir, { recursive: true }); fs.writeFileSync(filePath, content); } // Cache root path var rootDir; function findNodeModulesDir(root) { if (root === void 0) { root = process.cwd(); } var currentDir = root; while (currentDir !== path.parse(currentDir).root) { var nodeModulesPath = path.join(currentDir, 'node_modules'); if (fs.existsSync(nodeModulesPath)) { return nodeModulesPath; } currentDir = path.dirname(currentDir); } return ''; } // Cache nodeModulesDir result to avoid repeated calculations var cachedNodeModulesDir; function getNodeModulesDir() { if (!cachedNodeModulesDir) { cachedNodeModulesDir = findNodeModulesDir(rootDir); } return cachedNodeModulesDir; } function getSuffix(name) { var base = path.basename(name); var dotIndex = base.lastIndexOf('.'); if (dotIndex > 0 && dotIndex < base.length - 1) { return base.slice(dotIndex); } return '.js'; } var patternMap = {}; var cacheMap = {}; /** * Physically generate files as virtual modules under node_modules/__mf__virtual/* */ function assertModuleFound(tag, str) { if (str === void 0) { str = ''; } var module = VirtualModule.findModule(tag, str); if (!module) { throw new Error("Module Federation shared module '" + str + "' not found. Please ensure it's installed as a dependency in your package.json."); } return module; } var VirtualModule = /*#__PURE__*/function () { function VirtualModule(name, tag, suffix) { if (tag === void 0) { tag = '__mf_v__'; } if (suffix === void 0) { suffix = ''; } this.name = void 0; this.tag = void 0; this.suffix = void 0; this.inited = false; this.name = name; this.tag = tag; this.suffix = suffix || getSuffix(name); if (!cacheMap[this.tag]) cacheMap[this.tag] = {}; cacheMap[this.tag][this.name] = this; } /** * Set the root path for finding node_modules * @param root - Root path */ VirtualModule.setRoot = function setRoot(root) { rootDir = root; // Reset cache to ensure using the new root path cachedNodeModulesDir = undefined; } /** * Ensure virtual package directory exists */; VirtualModule.ensureVirtualPackageExists = function ensureVirtualPackageExists() { var nodeModulesDir = getNodeModulesDir(); var _getNormalizeModuleFe = getNormalizeModuleFederationOptions(), virtualModuleDir = _getNormalizeModuleFe.virtualModuleDir; var virtualPackagePath = path.resolve(nodeModulesDir, virtualModuleDir); if (!fs.existsSync(virtualPackagePath)) { fs.mkdirSync(virtualPackagePath); fs.writeFileSync(path.resolve(virtualPackagePath, 'empty.js'), ''); fs.writeFileSync(path.resolve(virtualPackagePath, 'package.json'), JSON.stringify({ name: virtualModuleDir, main: 'empty.js' })); } }; VirtualModule.findModule = function findModule(tag, str) { if (str === void 0) { str = ''; } if (!patternMap[tag]) patternMap[tag] = new RegExp("(.*" + packageNameEncode(tag) + "(.+?)" + packageNameEncode(tag) + ".*)"); var moduleName = (str.match(patternMap[tag]) || [])[2]; if (moduleName) return cacheMap[tag][packageNameDecode(moduleName)]; return undefined; }; var _proto = VirtualModule.prototype; _proto.getPath = function getPath() { return path.resolve(getNodeModulesDir(), this.getImportId()); }; _proto.getImportId = function getImportId() { var _getNormalizeModuleFe2 = getNormalizeModuleFederationOptions(), mfName = _getNormalizeModuleFe2.name, virtualModuleDir = _getNormalizeModuleFe2.virtualModuleDir; return virtualModuleDir + "/" + packageNameEncode("" + mfName + this.tag + this.name + this.tag) + this.suffix; }; _proto.writeSync = function writeSync(code, force) { if (!force && this.inited) return; if (!this.inited) { this.inited = true; } fs.writeFileSync(this.getPath(), code); }; _proto.write = function write(code) { fs.writeFile(this.getPath(), code, function () {}); }; return VirtualModule; }(); var VIRTUAL_EXPOSES = 'virtual:mf-exposes'; function generateExposes() { var options = getNormalizeModuleFederationOptions(); return "\n export default {\n " + Object.keys(options.exposes).map(function (key) { return "\n " + JSON.stringify(key) + ": async () => {\n const importModule = await import(" + JSON.stringify(options.exposes[key]["import"]) + ")\n const exportModule = {}\n Object.assign(exportModule, importModule)\n Object.defineProperty(exportModule, \"__esModule\", {\n value: true,\n enumerable: false\n })\n return exportModule\n }\n "; }).join(',') + "\n }\n "; } var virtualRuntimeInitStatus = new VirtualModule('runtimeInit'); function writeRuntimeInitStatus() { virtualRuntimeInitStatus.writeSync("\n let initResolve, initReject\n const initPromise = new Promise((re, rj) => {\n initResolve = re\n initReject = rj\n })\n module.exports = {\n initPromise,\n initResolve,\n initReject\n }\n "); } var cacheRemoteMap = {}; var LOAD_REMOTE_TAG = '__loadRemote__'; function getRemoteVirtualModule(remote, command) { if (!cacheRemoteMap[remote]) { cacheRemoteMap[remote] = new VirtualModule(remote, LOAD_REMOTE_TAG, '.js'); cacheRemoteMap[remote].writeSync(generateRemotes(remote, command)); } var virtual = cacheRemoteMap[remote]; return virtual; } var usedRemotesMap = { // remote1: {remote1/App, remote1, remote1/Button} }; function addUsedRemote(remoteKey, remoteModule) { if (!usedRemotesMap[remoteKey]) usedRemotesMap[remoteKey] = new Set(); usedRemotesMap[remoteKey].add(remoteModule); } function getUsedRemotesMap() { return usedRemotesMap; } function generateRemotes(id, command) { return "\n const {loadRemote} = require(\"@module-federation/runtime\")\n const {initPromise} = require(\"" + virtualRuntimeInitStatus.getImportId() + "\")\n const res = initPromise.then(_ => loadRemote(" + JSON.stringify(id) + "))\n const exportModule = " + (command !== 'build' ? '/*mf top-level-await placeholder replacement mf*/' : 'await ') + "initPromise.then(_ => res)\n module.exports = exportModule\n "; } /** * Even the resolveId hook cannot interfere with vite pre-build, * and adding query parameter virtual modules will also fail. * You can only proxy to the real file through alias */ // *** __prebuild__ var preBuildCacheMap = {}; var PREBUILD_TAG = '__prebuild__'; function writePreBuildLibPath(pkg) { if (!preBuildCacheMap[pkg]) preBuildCacheMap[pkg] = new VirtualModule(pkg, PREBUILD_TAG); preBuildCacheMap[pkg].writeSync(''); } function getPreBuildLibImportId(pkg) { if (!preBuildCacheMap[pkg]) preBuildCacheMap[pkg] = new VirtualModule(pkg, PREBUILD_TAG); var importId = preBuildCacheMap[pkg].getImportId(); return importId; } // *** __loadShare__ var LOAD_SHARE_TAG = '__loadShare__'; var loadShareCacheMap = {}; function getLoadShareModulePath(pkg) { if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG, '.js'); var filepath = loadShareCacheMap[pkg].getPath(); return filepath; } function writeLoadShareModule(pkg, shareItem, command) { loadShareCacheMap[pkg].writeSync("\n\n ;() => import(" + JSON.stringify(getPreBuildLibImportId(pkg)) + ").catch(() => {});\n // dev uses dynamic import to separate chunks\n " + (command !== 'build' ? ";() => import(" + JSON.stringify(pkg) + ").catch(() => {});" : '') + "\n const {loadShare} = require(\"@module-federation/runtime\")\n const {initPromise} = require(\"" + virtualRuntimeInitStatus.getImportId() + "\")\n const res = initPromise.then(_ => loadShare(" + JSON.stringify(pkg) + ", {\n customShareInfo: {shareConfig:{\n singleton: " + shareItem.shareConfig.singleton + ",\n strictVersion: " + shareItem.shareConfig.strictVersion + ",\n requiredVersion: " + JSON.stringify(shareItem.shareConfig.requiredVersion) + "\n }}}))\n const exportModule = " + (command !== 'build' ? '/*mf top-level-await placeholder replacement mf*/' : 'await ') + "res.then(factory => factory())\n module.exports = exportModule\n "); } var usedShares = new Set(); function getUsedShares() { return usedShares; } function addUsedShares(pkg) { usedShares.add(pkg); } // *** Expose locally provided shared modules here new VirtualModule('localSharedImportMap'); function getLocalSharedImportMapPath() { return getLocalSharedImportMapPath_temp(); // return localSharedImportMapModule.getPath() } var prevSharedCount; function writeLocalSharedImportMap() { var sharedCount = getUsedShares().size; if (prevSharedCount !== sharedCount) { prevSharedCount = sharedCount; writeLocalSharedImportMap_temp(generateLocalSharedImportMap()); // localSharedImportMapModule.writeSync(generateLocalSharedImportMap(), true) } } function generateLocalSharedImportMap() { var options = getNormalizeModuleFederationOptions(); return "\n const importMap = {\n " + Array.from(getUsedShares()).sort().map(function (pkg) { return "\n " + JSON.stringify(pkg) + ": async () => {\n let pkg = await import(\"" + getPreBuildLibImportId(pkg) + "\")\n return pkg\n }\n "; }).join(',') + "\n }\n const usedShared = {\n " + Array.from(getUsedShares()).sort().map(function (key) { var shareItem = getNormalizeShareItem(key); if (!shareItem) return null; return "\n " + JSON.stringify(key) + ": {\n name: " + JSON.stringify(key) + ",\n version: " + JSON.stringify(shareItem.version) + ",\n scope: [" + JSON.stringify(shareItem.scope) + "],\n loaded: false,\n from: " + JSON.stringify(options.name) + ",\n async get () {\n usedShared[" + JSON.stringify(key) + "].loaded = true\n const {" + JSON.stringify(key) + ": pkgDynamicImport} = importMap \n const res = await pkgDynamicImport()\n const exportModule = {...res}\n // All npm packages pre-built by vite will be converted to esm\n Object.defineProperty(exportModule, \"__esModule\", {\n value: true,\n enumerable: false\n })\n return function () {\n return exportModule\n }\n },\n shareConfig: {\n singleton: " + shareItem.shareConfig.singleton + ",\n requiredVersion: " + JSON.stringify(shareItem.shareConfig.requiredVersion) + "\n }\n }\n "; }).filter(function (x) { return x !== null; }).join(',') + "\n }\n const usedRemotes = [" + Object.keys(getUsedRemotesMap()).map(function (key) { var _JSON$stringify; var remote = options.remotes[key]; if (!remote) return null; return "\n {\n entryGlobalName: " + JSON.stringify(remote.entryGlobalName) + ",\n name: " + JSON.stringify(remote.name) + ",\n type: " + JSON.stringify(remote.type) + ",\n entry: " + JSON.stringify(remote.entry) + ",\n shareScope: " + ((_JSON$stringify = JSON.stringify(remote.shareScope)) != null ? _JSON$stringify : 'default') + ",\n }\n "; }).filter(function (x) { return x !== null; }).join(',') + "\n ]\n export {\n usedShared,\n usedRemotes\n }\n "; } var REMOTE_ENTRY_ID = 'virtual:mf-REMOTE_ENTRY_ID'; function generateRemoteEntry(options) { var pluginImportNames = options.runtimePlugins.map(function (p, i) { return ["$runtimePlugin_" + i, "import $runtimePlugin_" + i + " from \"" + p + "\";"]; }); return "\n import {init as runtimeInit, loadRemote} from \"@module-federation/runtime\";\n " + pluginImportNames.map(function (item) { return item[1]; }).join('\n') + "\n import exposesMap from \"" + VIRTUAL_EXPOSES + "\"\n import {usedShared, usedRemotes} from \"" + getLocalSharedImportMapPath() + "\"\n import {\n initResolve\n } from \"" + virtualRuntimeInitStatus.getImportId() + "\"\n const initTokens = {}\n const shareScopeName = " + JSON.stringify(options.shareScope) + "\n const mfName = " + JSON.stringify(options.name) + "\n async function init(shared = {}, initScope = []) {\n const initRes = runtimeInit({\n name: mfName,\n remotes: usedRemotes,\n shared: usedShared,\n plugins: [" + pluginImportNames.map(function (item) { return item[0] + "()"; }).join(', ') + "],\n " + (options.shareStrategy ? "shareStrategy: '" + options.shareStrategy + "'" : '') + "\n });\n // handling circular init calls\n var initToken = initTokens[shareScopeName];\n if (!initToken)\n initToken = initTokens[shareScopeName] = { from: mfName };\n if (initScope.indexOf(initToken) >= 0) return;\n initScope.push(initToken);\n initRes.initShareScopeMap('" + options.shareScope + "', shared);\n try {\n await Promise.all(await initRes.initializeSharing('" + options.shareScope + "', {\n strategy: '" + options.shareStrategy + "',\n from: \"build\",\n initScope\n }));\n } catch (e) {\n console.error(e)\n }\n initResolve(initRes)\n return initRes\n }\n\n function getExposes(moduleName) {\n if (!(moduleName in exposesMap)) throw new Error(`Module ${moduleName} does not exist in container.`)\n return (exposesMap[moduleName])().then(res => () => res)\n }\n export {\n init,\n getExposes as get\n }\n "; } /** * Inject entry file, automatically init when used as host, * and will not inject remoteEntry */ var HOST_AUTO_INIT_TAG = '__H_A_I__'; var hostAutoInitModule = new VirtualModule('hostAutoInit', HOST_AUTO_INIT_TAG); function writeHostAutoInit() { hostAutoInitModule.writeSync("\n const remoteEntryPromise = import(\"" + REMOTE_ENTRY_ID + "\")\n // __tla only serves as a hack for vite-plugin-top-level-await. \n Promise.resolve(remoteEntryPromise)\n .then(remoteEntry => {\n return Promise.resolve(remoteEntry.__tla)\n .then(remoteEntry.init).catch(remoteEntry.init)\n })\n "); } function getHostAutoInitImportId() { return hostAutoInitModule.getImportId(); } function getHostAutoInitPath() { return hostAutoInitModule.getPath(); } function initVirtualModules() { writeLocalSharedImportMap(); writeHostAutoInit(); writeRuntimeInitStatus(); } var ASSET_TYPES = ['js', 'css']; var LOAD_TIMINGS = ['sync', 'async']; var JS_EXTENSIONS = ['.ts', '.tsx', '.jsx', '.mjs', '.cjs']; /** * Creates an empty asset map structure for tracking JS and CSS assets * @returns Initialized asset map with sync/async arrays for JS and CSS */ var createEmptyAssetMap = function createEmptyAssetMap() { return { js: { sync: [], async: [] }, css: { sync: [], async: [] } }; }; /** * Tracks an asset in the preload map with deduplication * @param map - The preload map to update * @param key - The module key to track under * @param fileName - The asset filename to track * @param isAsync - Whether the asset is loaded async * @param type - The asset type ('js' or 'css') */ var trackAsset = function trackAsset(map, key, fileName, isAsync, type) { if (!map[key]) { map[key] = createEmptyAssetMap(); } var target = isAsync ? map[key][type].async : map[key][type].sync; if (!target.includes(fileName)) { target.push(fileName); } }; /** * Checks if a file is a CSS file by extension * @param fileName - The filename to check * @returns True if file has a CSS extension (.css, .scss, .less) */ var isCSSFile = function isCSSFile(fileName) { return fileName.endsWith('.css') || fileName.endsWith('.scss') || fileName.endsWith('.less'); }; /** * Collects all CSS assets from the bundle * @param bundle - The Rollup output bundle * @returns Set of CSS asset filenames */ var collectCssAssets = function collectCssAssets(bundle) { var cssAssets = new Set(); for (var _i = 0, _Object$entries = Object.entries(bundle); _i < _Object$entries.length; _i++) { var _Object$entries$_i = _Object$entries[_i], fileName = _Object$entries$_i[0], fileData = _Object$entries$_i[1]; if (fileData.type === 'asset' && isCSSFile(fileName)) { cssAssets.add(fileName); } } return cssAssets; }; /** * Processes module assets and tracks them in the files map * @param bundle - The Rollup output bundle * @param filesMap - The preload map to populate * @param moduleMatcher - Function that matches module paths to keys */ var processModuleAssets = function processModuleAssets(bundle, filesMap, moduleMatcher) { for (var _i2 = 0, _Object$entries2 = Object.entries(bundle); _i2 < _Object$entries2.length; _i2++) { var _Object$entries2$_i = _Object$entries2[_i2], fileName = _Object$entries2$_i[0], fileData = _Object$entries2$_i[1]; if (fileData.type !== 'chunk') continue; if (!fileData.modules) continue; for (var _i3 = 0, _Object$keys = Object.keys(fileData.modules); _i3 < _Object$keys.length; _i3++) { var modulePath = _Object$keys[_i3]; var matchKey = moduleMatcher(modulePath); if (!matchKey) continue; // Track main JS chunk trackAsset(filesMap, matchKey, fileName, false, 'js'); // Handle dynamic imports if (fileData.dynamicImports) { for (var _iterator = _createForOfIteratorHelperLoose(fileData.dynamicImports), _step; !(_step = _iterator()).done;) { var dynamicImport = _step.value; var importData = bundle[dynamicImport]; if (!importData) continue; var isCss = isCSSFile(dynamicImport); trackAsset(filesMap, matchKey, dynamicImport, true, isCss ? 'css' : 'js'); } } } } }; /** * Deduplicates assets in the files map * @param filesMap - The preload map to deduplicate * @returns New deduplicated preload map */ var deduplicateAssets = function deduplicateAssets(filesMap) { var result = {}; for (var _i4 = 0, _Object$entries3 = Object.entries(filesMap); _i4 < _Object$entries3.length; _i4++) { var _Object$entries3$_i = _Object$entries3[_i4], key = _Object$entries3$_i[0], assetMaps = _Object$entries3$_i[1]; result[key] = createEmptyAssetMap(); for (var _i5 = 0, _ASSET_TYPES = ASSET_TYPES; _i5 < _ASSET_TYPES.length; _i5++) { var type = _ASSET_TYPES[_i5]; for (var _i6 = 0, _LOAD_TIMINGS = LOAD_TIMINGS; _i6 < _LOAD_TIMINGS.length; _i6++) { var timing = _LOAD_TIMINGS[_i6]; result[key][type][timing] = Array.from(new Set(assetMaps[type][timing])); } } } return result; }; /** * Builds a mapping between module files and their share keys * @param shareKeys - Set of share keys to map * @param resolveFn - Function to resolve module paths * @returns Map of file paths to their corresponding share keys */ var buildFileToShareKeyMap = function buildFileToShareKeyMap(shareKeys, resolveFn) { try { var fileToShareKey = new Map(); return Promise.resolve(Promise.all(Array.from(shareKeys).map(function (shareKey) { return resolveFn(getPreBuildLibImportId(shareKey)).then(function (resolution) { var _resolution$id; return { shareKey: shareKey, file: resolution == null || (_resolution$id = resolution.id) == null ? void 0 : _resolution$id.split('?')[0] }; })["catch"](function () { return null; }); }))).then(function (resolutions) { for (var _iterator2 = _createForOfIteratorHelperLoose(resolutions), _step2; !(_step2 = _iterator2()).done;) { var resolution = _step2.value; if (resolution != null && resolution.file) { fileToShareKey.set(resolution.file, resolution.shareKey); } } return fileToShareKey; }); } catch (e) { return Promise.reject(e); } }; /** * Resolves the public path for remote entries * @param options - Module Federation options * @param viteBase - Vite's base config value * @param originalBase - Original base config before any transformations * @returns The resolved public path */ function resolvePublicPath(options, viteBase, originalBase) { // Use explicitly set publicPath if provided if (options.publicPath) { return options.publicPath; } // Handle empty original base case if (originalBase === '') { return 'auto'; } // Use viteBase if available, ensuring it ends with a slash if (viteBase) { return viteBase.replace(/\/?$/, '/'); } // Fallback to auto if no base is specified return 'auto'; } var Manifest = function Manifest() { var mfOptions = getNormalizeModuleFederationOptions(); var name = mfOptions.name, filename = mfOptions.filename, getPublicPath = mfOptions.getPublicPath, manifestOptions = mfOptions.manifest; var mfManifestName = ''; if (manifestOptions === true) { mfManifestName = 'mf-manifest.json'; } if (typeof manifestOptions !== 'boolean') { mfManifestName = path__namespace.join((manifestOptions == null ? void 0 : manifestOptions.filePath) || '', (manifestOptions == null ? void 0 : manifestOptions.fileName) || ''); } var root; var remoteEntryFile; var publicPath; var _command; var _originalConfigBase; var viteConfig; /** * Adds global CSS assets to all module exports * @param filesMap - The preload map to update * @param cssAssets - Set of CSS asset filenames to add */ var addCssAssetsToAllExports = function addCssAssetsToAllExports(filesMap, cssAssets) { Object.keys(filesMap).forEach(function (key) { cssAssets.forEach(function (cssAsset) { trackAsset(filesMap, key, cssAsset, false, 'css'); }); }); }; return [{ name: 'module-federation-manifest', apply: 'serve', /** * Stores resolved Vite config for later use */ /** * Finalizes configuration after all plugins are resolved * @param config - Fully resolved Vite config */ configResolved: function configResolved(config) { viteConfig = config; }, /** * Configures dev server middleware to handle manifest requests * @param server - Vite dev server instance */ configureServer: function configureServer(server) { server.middlewares.use(function (req, res, next) { var _req$url; if (!mfManifestName) { next(); return; } if (((_req$url = req.url) == null ? void 0 : _req$url.replace(/\?.*/, '')) === (viteConfig.base + mfManifestName).replace(/^\/?/, '/')) { res.setHeader('Content-Type', 'application/json'); res.setHeader('Access-Control-Allow-Origin', '*'); res.end(JSON.stringify(_extends({}, generateMFManifest({}), { id: name, name: name, metaData: { name: name, type: 'app', buildInfo: { buildVersion: '1.0.0', buildName: name }, remoteEntry: { name: filename, path: '', type: 'module' }, ssrRemoteEntry: { name: filename, path: '', type: 'module' }, types: { path: '', name: '' }, globalName: name, pluginVersion: '0.2.5', publicPath: publicPath } }))); } else { next(); } }); } }, { name: 'module-federation-manifest', enforce: 'post', /** * Initial plugin configuration * @param config - Vite config object * @param command - Current Vite command (serve/build) */ config: function config(_config, _ref) { var command = _ref.command; if (!_config.build) _config.build = {}; if (!_config.build.manifest) { _config.build.manifest = _config.build.manifest || !!manifestOptions; } _command = command; _originalConfigBase = _config.base; }, configResolved: function configResolved(config) { root = config.root; var base = config.base; if (_command === 'serve') { base = (config.server.origin || '') + config.base; } publicPath = resolvePublicPath(mfOptions, base, _originalConfigBase); }, /** * Generates the module federation manifest file * @param options - Rollup output options * @param bundle - Generated bundle assets */ generateBundle: function generateBundle(options, bundle) { try { var _this = this; if (!mfManifestName) return Promise.resolve(); var filesMap = {}; // First pass: Find remoteEntry file for (var _i = 0, _Object$entries = Object.entries(bundle); _i < _Object$entries.length; _i++) { var _Object$entries$_i = _Object$entries[_i], _ = _Object$entries$_i[0], fileData = _Object$entries$_i[1]; if (mfOptions.filename.replace(/[\[\]]/g, '_').replace(/\.[^/.]+$/, '') === fileData.name || fileData.name === 'remoteEntry') { remoteEntryFile = fileData.fileName; break; // We can break early since we only need to find remoteEntry once } } // Second pass: Collect all CSS assets var allCssAssets = collectCssAssets(bundle); var exposesModules = Object.keys(mfOptions.exposes).map(function (item) { return mfOptions.exposes[item]["import"]; }); // Process exposed modules processModuleAssets(bundle, filesMap, function (modulePath) { var absoluteModulePath = path__namespace.resolve(root, modulePath); return exposesModules.find(function (exposeModule) { var exposePath = path__namespace.resolve(root, exposeModule); // First try exact path match if (absoluteModulePath === exposePath) { return true; } // Then try path match without known extensions var getPathWithoutKnownExt = function getPathWithoutKnownExt(filePath) { var ext = path__namespace.extname(filePath); return JS_EXTENSIONS.includes(ext) ? path__namespace.join(path__namespace.dirname(filePath), path__namespace.basename(filePath, ext)) : filePath; }; var modulePathNoExt = getPathWithoutKnownExt(absoluteModulePath); var exposePathNoExt = getPathWithoutKnownExt(exposePath); return modulePathNoExt === exposePathNoExt; }); }); // Process shared modules return Promise.resolve(buildFileToShareKeyMap(getUsedShares(), _this.resolve.bind(_this))).then(function (fileToShareKey) { processModuleAssets(bundle, filesMap, function (modulePath) { return fileToShareKey.get(modulePath); }); // Add all CSS assets to every export addCssAssetsToAllExports(filesMap, allCssAssets); // Final deduplication of all assets filesMap = deduplicateAssets(filesMap); _this.emitFile({ type: 'asset', fileName: mfManifestName, source: JSON.stringify(generateMFManifest(filesMap)) }); }); } catch (e) { return Promise.reject(e); } } }]; /** * Generates the final manifest JSON structure * @param preloadMap - Map of module assets to include * @returns Complete manifest object */ function generateMFManifest(preloadMap) { var options = getNormalizeModuleFederationOptions(); var name = options.name; var remoteEntry = { name: remoteEntryFile, path: '', type: 'module' }; // Process remotes var remotes = Array.from(Object.entries(getUsedRemotesMap())).flatMap(function (_ref2) { var remoteKey = _ref2[0], modules = _ref2[1]; return Array.from(modules).map(function (moduleKey) { return { federationContainerName: options.remotes[remoteKey].entry, moduleName: moduleKey.replace(remoteKey, '').replace('/', ''), alias: remoteKey, entry: '*' }; }); }); // Process shared dependencies var shared = Array.from(getUsedShares()).map(function (shareKey) { var shareItem = getNormalizeShareItem(shareKey); var assets = preloadMap[shareKey] || createEmptyAssetMap(); return { id: name + ":" + shareKey, name: shareKey, version: shareItem.version, requiredVersion: shareItem.shareConfig.requiredVersion, assets: { js: { async: assets.js.async, sync: assets.js.sync }, css: { async: assets.css.async, sync: assets.css.sync } } }; }).filter(Boolean); // Process exposed modules var exposes = Object.entries(options.exposes).map(function (_ref3) { var key = _ref3[0], value = _ref3[1]; var formatKey = key.replace('./', ''); var sourceFile = value["import"]; var assets = preloadMap[sourceFile] || createEmptyAssetMap(); return { id: name + ":" + formatKey, name: formatKey, assets: { js: { async: assets.js.async, sync: assets.js.sync }, css: { async: assets.css.async, sync: assets.css.sync } }, path: key }; }).filter(Boolean); return { id: name, name: name, metaData: _extends({ name: name, type: 'app', buildInfo: { buildVersion: '1.0.0', buildName: name }, remoteEntry: remoteEntry, ssrRemoteEntry: remoteEntry, types: { path: '', name: '' }, globalName: name, pluginVersion: '0.2.5' }, !!getPublicPath ? { getPublicPath: getPublicPath } : { publicPath: publicPath }), shared: shared, remotes: remotes, exposes: exposes }; } }; var _resolve, promise = new Promise(function (resolve, reject) { _resolve = resolve; }); var parsePromise = promise; var exposesParseEnd = false; var parseStartSet = new Set(); var parseEndSet = new Set(); function pluginModuleParseEnd (excludeFn) { return [{ name: '_', apply: 'serve', config: function config() { // No waitin