@module-federation/vite 1.21.6 → 1.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -242,6 +242,27 @@ You can specify the place the host initialization file is injected with the **ho
242
242
  The **moduleParseTimeout** option allows you to configure the maximum time to wait for module parsing during the build process.
243
243
  The **moduleParseIdleTimeout** option is an alternative that resets the timer on every parsed module. It only fires when there has been no module activity for the configured duration, making it suitable for large codebases where the total build time exceeds the fixed timeout.
244
244
 
245
+ ## SSR entry loading strategy
246
+
247
+ SSR hosts can choose how HTTP ESM remote entries are evaluated during build and preview:
248
+
249
+ ```ts
250
+ federation({
251
+ name: "host",
252
+ remotes: {
253
+ // ...
254
+ },
255
+ ssrEntryLoader: {
256
+ strategy: "vm",
257
+ },
258
+ });
259
+ ```
260
+
261
+ - `"temp-file"` (default) fetches the remote graph, rewrites imports to host-resolved shared packages, writes temporary files, and loads them with `import()`.
262
+ - `"vm"` evaluates the graph in memory with `vm.SourceTextModule` and resolves shared packages through the Module Federation share scope.
263
+
264
+ The `"vm"` strategy requires Node.js to run with `--experimental-vm-modules`. When unavailable, the loader warns once and falls back to `"temp-file"`. Vite 8 development uses `ModuleRunner`; this option primarily affects build and preview SSR entry loading.
265
+
245
266
  ## Runtime capability optimization
246
267
 
247
268
  Runtime features that a build never uses can be removed at build time:
@@ -326,9 +347,9 @@ This deployment step is separate from the local Vite build; the plugin only emit
326
347
 
327
348
  ## External runtime (`experiments`)
328
349
 
329
- Share one `@module-federation/runtime-core` instance from a pure consumer host so remotes do not bundle their own copy. Pair the flags — remotes with `externalRuntime` require a host that provides the global.
350
+ Share one `@module-federation/runtime-core` instance from the host so remotes do not bundle their own copy. Pair the flags — remotes with `externalRuntime` require a host that provides the global.
330
351
 
331
- **Host (pure consumer, no `exposes`):**
352
+ **Host:**
332
353
 
333
354
  ```ts
334
355
  federation({
@@ -361,14 +382,14 @@ federation({
361
382
  });
362
383
  ```
363
384
 
364
- `provideExternalRuntime` injects a local runtime plugin that publishes `runtime-core` on `globalThis._FEDERATION_RUNTIME_CORE`. `externalRuntime` rewrites imports of `@module-federation/runtime-core` to read that global. Using `provideExternalRuntime` together with `exposes` throws only pure consumers may provide the runtime.
385
+ `provideExternalRuntime` injects a local runtime plugin that publishes `runtime-core` on `globalThis._FEDERATION_RUNTIME_CORE`. `externalRuntime` rewrites imports of `@module-federation/runtime-core` to read that global. A container that also `exposes` (e.g. a host consumed by its own remotes) may provide the runtime too, as long as exactly one container on the page does and it is loaded before any `externalRuntime` remote evaluates (a second provider is ignored with a `Detect multiple module federation runtime!` warning; a remote evaluated before the provider throws `_FEDERATION_RUNTIME_CORE is missing`).
365
386
  The `externalRuntime` rewrite applies to the browser remote graph; SSR remote entries continue to resolve `@module-federation/runtime-core` from Node so they do not depend on the browser global.
366
387
 
367
388
  ## ⚠️ `codeSplitting` is managed by the plugin
368
389
 
369
390
  Do not set `build.rollupOptions.output.codeSplitting` or
370
391
  `build.rolldownOptions.output.codeSplitting` to `false` — it will be **ignored** (with a warning).
371
- Module Federation requires chunk splitting so `loadShare` and `runtimeInitStatus` stay isolated for correct bootstrap order.
392
+ Module Federation requires chunk splitting so `runtimeInitStatus` and deferred `loadShare` wrappers stay isolated for correct bootstrap order. Eager `loadShare` wrappers are coalesced into one `loadShare-eager` chunk on Vite 8+ to reduce startup requests.
372
393
 
373
394
  ### `codeSplitting.groups` (Vite 8+ / Rolldown)
374
395
 
@@ -2,6 +2,7 @@ import { existsSync, readFileSync, readdirSync } from "fs";
2
2
  import { createRequire } from "module";
3
3
  import * as path$1 from "node:path";
4
4
  import { fileURLToPath, pathToFileURL } from "url";
5
+ import { createHash } from "node:crypto";
5
6
  //#region src/utils/logger.ts
6
7
  const MODULE_FEDERATION_LOG_PREFIX = "[Module Federation]";
7
8
  function formatModuleFederationMessage(message) {
@@ -136,22 +137,37 @@ function getPackageExportsTarget(pkg, packageName, exportsField) {
136
137
  * - => 3
137
138
  * . => 4
138
139
  */
140
+ const MF_HASHED_NAME_THRESHOLD = 90;
141
+ const MF_HASHED_NAME_HASH_LENGTH = 16;
142
+ const MF_HASHED_NAME_PREFIX_LENGTH = MF_HASHED_NAME_THRESHOLD - MF_HASHED_NAME_HASH_LENGTH;
143
+ const mfHashedNameMap = /* @__PURE__ */ new Map();
139
144
  /**
140
- * Encodes a package name into a valid file name.
141
- * @param {string} name - The package name, e.g., "@scope/xx-xx.xx".
145
+ * Encodes a package name (or shared-module specifier, which may include a
146
+ * deep import subpath) into a valid file name, falling back to a
147
+ * readable-prefix + content-hash id when the plain encoding would be too
148
+ * long for a filesystem path segment.
149
+ * @param {string} name - The package name or specifier, e.g., "@scope/xx-xx.xx" or "@scope/pkg/deep/sub-path".
142
150
  * @returns {string} - The encoded file name.
143
151
  */
144
152
  function packageNameEncode(name) {
145
153
  if (typeof name !== "string") throw createModuleFederationError("A string package name is required");
146
- return name.replace(/@/g, "_mf_0_").replace(/\//g, "_mf_1_").replace(/-/g, "_mf_2_").replace(/\./g, "_mf_3_");
154
+ const encoded = name.replace(/@/g, "_mf_0_").replace(/\//g, "_mf_1_").replace(/-/g, "_mf_2_").replace(/\./g, "_mf_3_");
155
+ if (encoded.length <= MF_HASHED_NAME_THRESHOLD) return encoded;
156
+ const hashedName = `${encoded.slice(0, MF_HASHED_NAME_PREFIX_LENGTH)}${createHash("sha256").update(name).digest("hex").slice(0, MF_HASHED_NAME_HASH_LENGTH)}`;
157
+ mfHashedNameMap.set(hashedName, name);
158
+ return hashedName;
147
159
  }
148
160
  /**
149
- * Decodes an encoded file name back to the original package name.
161
+ * Decodes an encoded file name back to the original package name or
162
+ * shared-module specifier, whether it was plainly substituted or hashed
163
+ * down by `packageNameEncode`.
150
164
  * @param {string} encoded - The encoded file name, e.g., "_mf_0_scope_mf_1_xx_mf_2_xx_mf_3_xx".
151
- * @returns {string} - The decoded package name.
165
+ * @returns {string} - The decoded package name or specifier.
152
166
  */
153
167
  function packageNameDecode(encoded) {
154
168
  if (typeof encoded !== "string") throw createModuleFederationError("A string encoded file name is required");
169
+ const original = mfHashedNameMap.get(encoded);
170
+ if (original !== void 0) return original;
155
171
  return encoded.replace(/_mf_0_/g, "@").replace(/_mf_1_/g, "/").replace(/_mf_2_/g, "-").replace(/_mf_3_/g, ".");
156
172
  }
157
173
  /**
package/lib/index.d.ts CHANGED
@@ -126,6 +126,13 @@ type ModuleFederationOptions = {
126
126
  * add any other Node-only packages that should not be bundled into the SSR entry.
127
127
  */
128
128
  ssrExternals?: string[];
129
+ /**
130
+ * Options for the auto-injected `@module-federation/vite/ssrEntryLoader`.
131
+ * When omitted, the loader uses the `'temp-file'` strategy. Set
132
+ * `strategy: 'vm'` to opt into `vm.SourceTextModule` evaluation while keeping
133
+ * the computed `resolvedShared` map.
134
+ */
135
+ ssrEntryLoader?: SsrEntryLoaderConfig;
129
136
  /**
130
137
  * Experimental Module Federation capabilities.
131
138
  *
@@ -141,13 +148,28 @@ interface PluginExperimentsOptions {
141
148
  */
142
149
  externalRuntime?: boolean;
143
150
  /**
144
- * Pure-consumer only (no `exposes`). Injects a local runtime plugin that
145
- * publishes `runtime-core` on `globalThis._FEDERATION_RUNTIME_CORE`.
151
+ * Injects a local runtime plugin that publishes `runtime-core` on
152
+ * `globalThis._FEDERATION_RUNTIME_CORE`. Set it on exactly one container
153
+ * per page; that container may also `exposes`.
146
154
  */
147
155
  provideExternalRuntime?: boolean;
148
156
  /** Generate the React SSR/hydration island capability for eligible exposes. */
149
157
  ssrMode?: 'ISLAND';
150
158
  }
159
+ type SsrEntryLoaderStrategy = 'temp-file' | 'vm';
160
+ type SsrEntryLoaderConfig = {
161
+ /**
162
+ * How the auto-injected `@module-federation/vite/ssrEntryLoader` evaluates
163
+ * remote SSR entries.
164
+ *
165
+ * - `'temp-file'` (default when omitted): fetch the ESM graph, rewrite
166
+ * specifiers, write temp files and `import()` them.
167
+ * - `'vm'`: evaluate the graph with `vm.SourceTextModule`. Requires
168
+ * `--experimental-vm-modules`; the loader emits a single warning and
169
+ * falls back to `'temp-file'` when that API is unavailable.
170
+ */
171
+ strategy?: SsrEntryLoaderStrategy;
172
+ };
151
173
  type HostInitInjectLocationOptions = 'entry' | 'html';
152
174
  interface PluginDevOptions {
153
175
  disableLiveReload?: boolean;
@@ -227,4 +249,4 @@ interface DtsHostOptions {
227
249
  declare function federation(mfUserOptions: ModuleFederationOptions): any[];
228
250
  declare function createModuleFederationConfig<T extends ModuleFederationOptions>(options: T): T;
229
251
  //#endregion
230
- export { type ModuleFederationOptions, type PluginExperimentsOptions, type PluginManifestOptions, type TreeShakingConfig, createModuleFederationConfig, federation };
252
+ export { type ModuleFederationOptions, type PluginExperimentsOptions, type PluginManifestOptions, type SsrEntryLoaderConfig, type SsrEntryLoaderStrategy, type TreeShakingConfig, createModuleFederationConfig, federation };
package/lib/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { i as resolveHashPlaceholderFileName, n as normalizePathForImport, r as rebaseImport } from "./buildPaths-BoaQTkxt.js";
2
- import { a as getPackageDetectionCwd, c as getSharedCacheDescriptor, d as packageNameDecode, f as packageNameEncode, g as createModuleFederationError, h as sharedCacheHelperCode, i as getIsRolldown, l as hasPackageDependency, m as setPackageDetectionCwd, n as getInstalledPackageEntry, o as getPackageName, p as resolveImportPath, r as getInstalledPackageJson, s as getPackageNameFromNodeModulePath, u as isNuxtProjectRoot, v as mfWarn } from "./dtsConstants-BsaLBaaK.js";
2
+ import { a as getPackageDetectionCwd, c as getSharedCacheDescriptor, d as packageNameDecode, f as packageNameEncode, g as createModuleFederationError, h as sharedCacheHelperCode, i as getIsRolldown, l as hasPackageDependency, m as setPackageDetectionCwd, n as getInstalledPackageEntry, o as getPackageName, p as resolveImportPath, r as getInstalledPackageJson, s as getPackageNameFromNodeModulePath, u as isNuxtProjectRoot, v as mfWarn } from "./dtsConstants-BEGrtvcw.js";
3
3
  import { a as filterId, c as getCommonSharedSubpaths, d as isNodeModulePath, f as isNuxtClientBase, h as resolvePublicPath, i as ensureTrailingSlash, l as getMatchingNodeModuleSubpath, m as normalizeNodeModulePath, n as invalidateSharedKeyMatcher, o as getBasePath$1, p as isViteOptimizableEntry, r as matchesSharedSource, s as getCommonSharedSubpathFromNodeModulePath, t as findSharedKey, u as isAssetLikeImport } from "./sharedKeyMatcher-DiUzRVH1.js";
4
4
  import { createRequire } from "node:module";
5
5
  import * as fs$2 from "fs";
@@ -373,6 +373,38 @@ async function mapCodeToCodeWithSourcemap(code) {
373
373
  };
374
374
  }
375
375
  //#endregion
376
+ //#region src/utils/remoteConsumerTarget.ts
377
+ function getPluginEnvironmentName(ctx) {
378
+ if (ctx == null || typeof ctx !== "object") return void 0;
379
+ const environment = ctx["environment"];
380
+ if (environment == null || typeof environment !== "object") return void 0;
381
+ const name = environment["name"];
382
+ return typeof name === "string" ? name : void 0;
383
+ }
384
+ /**
385
+ * Classify a plugin hook context's Vite environment. Environment names are
386
+ * user-defined, so Vite's `config.consumer` is the semantic role; fall back to
387
+ * the name only when it is missing (Vite 5–7). Returns `undefined` when the hook
388
+ * has no environment context at all.
389
+ */
390
+ function resolveEnvironmentConsumerTarget(ctx) {
391
+ if (ctx == null || typeof ctx !== "object") return void 0;
392
+ const environment = ctx["environment"];
393
+ if (environment == null || typeof environment !== "object") return void 0;
394
+ const consumer = environment.config?.consumer;
395
+ if (consumer === "client" || consumer === "server") return consumer;
396
+ const envName = getPluginEnvironmentName(ctx);
397
+ return !envName || envName === "client" ? "client" : "server";
398
+ }
399
+ /** Vite 5–7 hooks have no environment context and keep their client build behavior. */
400
+ function isClientEnvironment(ctx) {
401
+ return resolveEnvironmentConsumerTarget(ctx) !== "server";
402
+ }
403
+ function resolveRemoteConsumer(ctx, hasMultiEnvironment) {
404
+ if (!hasMultiEnvironment) return "unified";
405
+ return resolveEnvironmentConsumerTarget(ctx) ?? "client";
406
+ }
407
+ //#endregion
376
408
  //#region src/utils/codePositionMap.ts
377
409
  const REGEX_PREFIX_KEYWORDS = /* @__PURE__ */ new Set([
378
410
  "await",
@@ -887,6 +919,11 @@ function normalizeExperiments(experiments) {
887
919
  ssrMode: experiments?.ssrMode === "ISLAND" ? "ISLAND" : void 0
888
920
  };
889
921
  }
922
+ function normalizeSsrEntryLoader(ssrEntryLoader) {
923
+ const strategy = ssrEntryLoader?.strategy;
924
+ if (strategy !== "temp-file" && strategy !== "vm") return void 0;
925
+ return { strategy };
926
+ }
890
927
  let config;
891
928
  let explicitSharedKeys = /* @__PURE__ */ new Set();
892
929
  const explicitSharedKeysByOptions = /* @__PURE__ */ new WeakMap();
@@ -905,6 +942,18 @@ function resolveRuntimeImplementation() {
905
942
  function getNormalizeModuleFederationOptions() {
906
943
  return config;
907
944
  }
945
+ function hasRemotes(options = getNormalizeModuleFederationOptions()) {
946
+ return Object.keys(options.remotes || {}).length > 0;
947
+ }
948
+ function isRemoteContainer(options = getNormalizeModuleFederationOptions()) {
949
+ return Object.keys(options.exposes || {}).length > 0;
950
+ }
951
+ function isRemoteOnlyContainer(options = getNormalizeModuleFederationOptions()) {
952
+ return isRemoteContainer(options) && !hasRemotes(options);
953
+ }
954
+ function isLocalOnlyContainer(options = getNormalizeModuleFederationOptions()) {
955
+ return !isRemoteContainer(options) && !hasRemotes(options);
956
+ }
908
957
  function isExplicitSharedKey(key, options) {
909
958
  return (options ? explicitSharedKeysByOptions.get(options) : explicitSharedKeys)?.has(key) ?? false;
910
959
  }
@@ -945,6 +994,7 @@ function normalizeModuleFederationOptions(options) {
945
994
  varFilename: options.varFilename,
946
995
  target: options.target,
947
996
  ssrExternals: options.ssrExternals,
997
+ ssrEntryLoader: normalizeSsrEntryLoader(options.ssrEntryLoader),
948
998
  disableRemote: options.disableRemote,
949
999
  disableShared: options.disableShared,
950
1000
  disableSnapshot: options.disableSnapshot,
@@ -1022,11 +1072,14 @@ var VirtualModule = class VirtualModule {
1022
1072
  cacheMap[this.tag][this.name] = this;
1023
1073
  }
1024
1074
  getImportId() {
1025
- const importIdKey = `${this.scopeName ?? getNormalizeModuleFederationOptions().internalName}${this.tag}${this.name}${this.tag}`;
1075
+ const mfName = this.scopeName ?? getNormalizeModuleFederationOptions().internalName;
1076
+ const importIdKey = `${mfName}${this.tag}${this.name}${this.tag}`;
1026
1077
  if (this.importId && this.importIdKey === importIdKey) return this.importId;
1027
1078
  if (this.importId) delete idCacheMap[this.importId];
1028
1079
  this.importIdKey = importIdKey;
1029
- this.importId = `virtual:mf:${packageNameEncode(importIdKey)}${this.suffix}`;
1080
+ const namePart = packageNameEncode(this.name);
1081
+ const mfNamePart = packageNameEncode(mfName);
1082
+ this.importId = `virtual:mf:${mfNamePart}${this.tag}${namePart}${this.tag}${this.suffix}`;
1030
1083
  idCacheMap[this.importId] = this;
1031
1084
  return this.importId;
1032
1085
  }
@@ -2191,8 +2244,12 @@ function getPackageEsmEntryPath(pkg) {
2191
2244
  }
2192
2245
  const packageNamedExportsCache = /* @__PURE__ */ new Map();
2193
2246
  const sharedExportInspectionCache = /* @__PURE__ */ new Map();
2247
+ const sharedMutableExportsCache = /* @__PURE__ */ new Map();
2194
2248
  function invalidateSharedExportInspectionCache(filePath) {
2195
- if (!/(?:^|[/\\])node_modules(?:[/\\]|$)/.test(filePath)) sharedExportInspectionCache.clear();
2249
+ if (!/(?:^|[/\\])node_modules(?:[/\\]|$)/.test(filePath)) {
2250
+ sharedExportInspectionCache.clear();
2251
+ sharedMutableExportsCache.clear();
2252
+ }
2196
2253
  }
2197
2254
  const DEFAULT_SHARED_EXPORT_CONDITIONS = [
2198
2255
  "browser",
@@ -2278,7 +2335,7 @@ function getMutableExportsFromFile(entryPath, exportConditions = DEFAULT_SHARED_
2278
2335
  if (isValidEsmExportName(exported) && (mutableBindings.has(local) || reExportedMutable.has(local))) mutableExports.add(exported);
2279
2336
  }
2280
2337
  }
2281
- const starExportRegex = /export\s+\*\s+from\s+['"]([^'"]+)['"]/g;
2338
+ const starExportRegex = /export\s*\*\s*from\s*['"]([^'"]+)['"]/g;
2282
2339
  while ((match = starExportRegex.exec(source)) !== null) {
2283
2340
  if (!codePositions[match.index]) continue;
2284
2341
  const resolved = resolveReExportModule(entryPath, match[1], exportConditions);
@@ -2293,10 +2350,18 @@ function getMutableExportsFromFile(entryPath, exportConditions = DEFAULT_SHARED_
2293
2350
  }
2294
2351
  function getSharedMutableExports(pkg, shareItem, exportConditions = DEFAULT_SHARED_EXPORT_CONDITIONS) {
2295
2352
  const configuredImport = shareItem?.shareConfig.import;
2296
- return getMutableExportsFromFile(typeof configuredImport === "string" ? resolveConfiguredImportPath(configuredImport, exportConditions) : getInstalledPackageEntry(pkg, {
2353
+ const entryPath = typeof configuredImport === "string" ? resolveConfiguredImportPath(configuredImport, exportConditions) : getInstalledPackageEntry(pkg, {
2297
2354
  conditions: exportConditions,
2298
2355
  resolveSubpathWithRequire: false
2299
- }), exportConditions);
2356
+ });
2357
+ if (!entryPath) return [];
2358
+ const cacheKey = `${entryPath}\0${exportConditions.join("\0")}`;
2359
+ let mutableExports = sharedMutableExportsCache.get(cacheKey);
2360
+ if (!mutableExports) {
2361
+ mutableExports = getMutableExportsFromFile(entryPath, exportConditions);
2362
+ sharedMutableExportsCache.set(cacheKey, mutableExports);
2363
+ }
2364
+ return mutableExports;
2300
2365
  }
2301
2366
  function resolveConfiguredImportPath(importSource, exportConditions = DEFAULT_SHARED_EXPORT_CONDITIONS) {
2302
2367
  if (path$1.isAbsolute(importSource)) return resolveFileLikeModule(importSource);
@@ -2609,15 +2674,15 @@ function getNamedExportsViaRegex(source, filePath, visited, scanState = { comple
2609
2674
  else if (name === "default" || name === "__esModule") {} else scanState.complete = false;
2610
2675
  }
2611
2676
  }
2612
- const namespaceReExportRegex = new RegExp(`export\\s+\\*\\s+as\\s+(${JS_IDENTIFIER_PATTERN})\\s+from\\s+['"][^'"]+['"]`, "gu");
2677
+ const namespaceReExportRegex = new RegExp(`export\\s*\\*\\s*as\\s+(${JS_IDENTIFIER_PATTERN})\\s*from\\s*['"][^'"]+['"]`, "gu");
2613
2678
  while ((match = namespaceReExportRegex.exec(source)) !== null) {
2614
2679
  if (!codePositions[match.index]) continue;
2615
2680
  recognizedExportStarts.add(match.index);
2616
2681
  if (isValidEsmExportName(match[1])) names.add(match[1]);
2617
2682
  }
2618
- if (hasCodeMatch(source, /export\s+\*\s+as\s+['"]/g, codePositions)) scanState.complete = false;
2683
+ if (hasCodeMatch(source, /export\s*\*\s*as\s*['"]/g, codePositions)) scanState.complete = false;
2619
2684
  if (filePath) {
2620
- const starExportRegex = /export\s+\*\s+from\s+['"]([^'"]+)['"]/g;
2685
+ const starExportRegex = /export\s*\*\s*from\s*['"]([^'"]+)['"]/g;
2621
2686
  while ((match = starExportRegex.exec(source)) !== null) {
2622
2687
  if (!codePositions[match.index]) continue;
2623
2688
  recognizedExportStarts.add(match.index);
@@ -2852,12 +2917,6 @@ function isSharedSingletonConsumedByPeer(pkg, options = getNormalizeModuleFedera
2852
2917
  };
2853
2918
  return Array.from(sharedKeyByPackageName.values()).some((sharedPkg) => sharedPkg !== pkg && reachesPkg(sharedPkg, /* @__PURE__ */ new Set([sharedPkg])));
2854
2919
  }
2855
- function isRemoteOnlyContainer(options = getNormalizeModuleFederationOptions()) {
2856
- return Object.keys(options.exposes || {}).length > 0 && Object.keys(options.remotes || {}).length === 0;
2857
- }
2858
- function isLocalOnlyContainer(options = getNormalizeModuleFederationOptions()) {
2859
- return Object.keys(options.exposes || {}).length === 0 && Object.keys(options.remotes || {}).length === 0;
2860
- }
2861
2920
  function tryResolveImportFromPackageRoot(pkg, root) {
2862
2921
  try {
2863
2922
  return resolveWorkspaceEsmEntry(pkg, createRequire$1(pathToFileURL(path$1.join(root, "package.json"))).resolve(pkg), root);
@@ -3378,11 +3437,10 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
3378
3437
  const liveNamedExportLine = liveNamedExports.length ? `export { ${liveNamedExports.join(", ")} } from ${escapeGeneratedStringLiteral(sharedImportSource)};` : "";
3379
3438
  const hasCompleteExportCoverage = detectedNamedExports !== void 0;
3380
3439
  const isWorkspaceSingleton = isWorkspacePackage && shareItem.shareConfig.singleton === true;
3381
- const isDefaultShareScope = shareItem.scope === void 0 || shareItem.scope === "default" || Array.isArray(shareItem.scope) && shareItem.scope[0] === "default";
3382
- const usesDeferredSingletonFallback = hasCompleteExportCoverage && shareItem.shareConfig.eager !== true && (isWorkspacePackage || command !== "build" && isRemoteOnlyContainer(resolvedOptions) && shareItem.shareConfig.singleton === true || command === "build" && isRemoteOnlyContainer(resolvedOptions) && (shareItem.shareConfig.singleton === true || isDefaultShareScope) && !isSharedSingletonConsumedByPeer(pkg, resolvedOptions, true));
3440
+ const usesDeferredSingletonFallback = hasCompleteExportCoverage && shareItem.shareConfig.eager !== true && (isWorkspacePackage || command !== "build" && isRemoteOnlyContainer(resolvedOptions) && shareItem.shareConfig.singleton === true || command === "build" && isRemoteContainer(resolvedOptions) && !isSharedSingletonConsumedByPeer(pkg, resolvedOptions, true));
3383
3441
  const servesRemoteSingletonFallback = command !== "build" && isRemoteOnlyContainer(resolvedOptions) && shareItem.shareConfig.singleton === true;
3384
3442
  const isConsumedByPeerSingleton = isSharedSingletonConsumedByPeer(pkg, resolvedOptions);
3385
- const usesEntryInjectedRemoteFallback = hasCompleteExportCoverage && !isWorkspaceSingleton && isRemoteOnlyContainer(resolvedOptions) && shareItem.shareConfig.singleton === true && resolvedOptions.hostInitInjectLocation === "entry" && (command === "build" || isConsumedByPeerSingleton);
3443
+ const usesEntryInjectedRemoteFallback = hasCompleteExportCoverage && !isWorkspaceSingleton && isRemoteContainer(resolvedOptions) && shareItem.shareConfig.singleton === true && resolvedOptions.hostInitInjectLocation === "entry" && (command === "build" || isConsumedByPeerSingleton);
3386
3444
  const usesEagerWorkspaceFallback = hasCompleteExportCoverage && isWorkspaceSingleton && !servesRemoteSingletonFallback && (isConsumedByPeerSingleton || shareItem.shareConfig.eager === true);
3387
3445
  const usesDeferredTreeShakingFallback = hasCompleteExportCoverage && Boolean(treeShakingConsumer);
3388
3446
  const reactMixedModeGuard = pkg === "react" ? createReactMixedModeRuntimeGuard() : "";
@@ -3566,6 +3624,7 @@ function generateLocalSharedImportMap(options) {
3566
3624
  const useDirectReactImport = shouldUseDirectReactImport();
3567
3625
  const orderedShares = getOrderedUsedShares(options);
3568
3626
  const sharesToMaterialize = new Set(getMaterializedShares(options));
3627
+ const hasConsumeOnlyShare = orderedShares.some((pkg) => getNormalizeShareItem(pkg, resolvedOptions)?.shareConfig.import === false);
3569
3628
  return `
3570
3629
  import {loadShare} from "@module-federation/runtime";
3571
3630
  ${orderedShares.map((pkg, index) => {
@@ -3574,12 +3633,47 @@ function generateLocalSharedImportMap(options) {
3574
3633
  return `import * as __mfEagerShare_${index} from ${toSafeJsLiteral(getLocalSharedPackagePath(pkg, shareItem, options))};`;
3575
3634
  }).filter(Boolean).join("\n")}
3576
3635
  ${normalizeRuntimeShareCode}
3636
+ const __mfGetCachedReactFamily = (keys, reactKeys, localVersion, requiredExport) => {
3637
+ const cache = globalThis.__mf_module_cache__?.share;
3638
+ const react = reactKeys.map((key) => cache?.[key]).find((value) => value !== undefined);
3639
+ const reactVersion = react?.version ?? react?.default?.version;
3640
+ const actual = String(reactVersion || '').split(/[^0-9]+/).map(Number);
3641
+ const expected = String(localVersion || '').split(/[^0-9]+/).map(Number);
3642
+ for (let index = 0; index < Math.max(actual.length, expected.length); index++) {
3643
+ if ((actual[index] || 0) < (expected[index] || 0)) return undefined;
3644
+ if ((actual[index] || 0) > (expected[index] || 0)) break;
3645
+ }
3646
+ for (const key of keys) {
3647
+ const cached = cache?.[key];
3648
+ if (cached === undefined) continue;
3649
+ if (!requiredExport || typeof cached?.[requiredExport] === 'function' || typeof cached?.default?.[requiredExport] === 'function') return cached;
3650
+ }
3651
+ return undefined;
3652
+ };
3653
+ ${hasConsumeOnlyShare ? `// A consume-only share has no local module: its entry is the same shape for every key, so one helper builds it instead of a literal per key
3654
+ const __mfHostOnly = (name) => async () => {
3655
+ throw new Error(\`[Module Federation] Shared module '\${name}' must be provided by host\`);
3656
+ };
3657
+ const __mfConsumeOnly = (name, version, scope, materialize, shareConfig) => ({
3658
+ name,
3659
+ version,
3660
+ scope: [scope],
3661
+ loaded: false,
3662
+ materialize,
3663
+ eager: shareConfig.eager,
3664
+ from: ${toSafeJsLiteral(resolvedOptions.name)},
3665
+ canLiveRebind: true,
3666
+ get: __mfHostOnly(name),
3667
+ shareConfig: { ...shareConfig, import: false },
3668
+ });` : ""}
3577
3669
  const importMap = {
3578
3670
  ${orderedShares.map((pkg, index) => {
3579
3671
  const shareItem = getNormalizeShareItem(pkg, resolvedOptions);
3672
+ if (shareItem?.shareConfig.import === false) return `
3673
+ ${toSafeJsLiteral(pkg)}: __mfHostOnly(${toSafeJsLiteral(pkg)})`;
3580
3674
  return `
3581
3675
  ${toSafeJsLiteral(pkg)}: async () => {
3582
- ${shareItem?.shareConfig.import === false ? `throw new Error(\`[Module Federation] Shared module '\${${toSafeJsLiteral(pkg)}}' must be provided by host\`);` : shareItem?.shareConfig.eager ? `let pkg = __mfEagerShare_${index};
3676
+ ${shareItem?.shareConfig.eager ? `let pkg = __mfEagerShare_${index};
3583
3677
  return pkg;` : `let pkg = await import(${toSafeJsLiteral(getLocalSharedPackagePath(pkg, shareItem, options))});
3584
3678
  return pkg;`}
3585
3679
  }
@@ -3590,9 +3684,20 @@ function generateLocalSharedImportMap(options) {
3590
3684
  ${orderedShares.map((key) => {
3591
3685
  const shareItem = getNormalizeShareItem(key, resolvedOptions);
3592
3686
  if (!shareItem) return null;
3687
+ const isReactFamily = key.startsWith("react/") || key === "react-dom/client";
3688
+ const cacheKeys = [key, ...key === "react-dom/client" ? ["react-dom"] : []].flatMap((pkg) => {
3689
+ const descriptor = getSharedCacheDescriptor(pkg, shareItem);
3690
+ return [descriptor.canonical, ...descriptor.aliases ?? []];
3691
+ });
3692
+ const reactCacheKeys = ["react"].flatMap((pkg) => {
3693
+ const descriptor = getSharedCacheDescriptor(pkg, shareItem);
3694
+ return [descriptor.canonical, ...descriptor.aliases ?? []];
3695
+ });
3593
3696
  const detectedNamedExports = getSharedNamedExports(key, shareItem);
3594
3697
  const canLiveRebind = shareItem.shareConfig.import === false || detectedNamedExports !== void 0;
3595
3698
  const treeShakingConfig = canLiveRebind ? shareItem.shareConfig.treeShaking : void 0;
3699
+ if (shareItem.shareConfig.import === false && !treeShakingConfig) return `
3700
+ ${toSafeJsLiteral(key)}: __mfConsumeOnly(${toSafeJsLiteral(key)}, ${toSafeJsLiteral(shareItem.version)}, ${toSafeJsLiteral(shareItem.scope)}, ${sharesToMaterialize.has(key)}, {singleton: ${shareItem.shareConfig.singleton}, requiredVersion: ${toSafeJsLiteral(shareItem.shareConfig.requiredVersion)}, strictVersion: ${shareItem.shareConfig.strictVersion}, eager: ${Boolean(shareItem.shareConfig.eager)}})`;
3596
3701
  const treeShakingUsage = treeShakingConfig ? getTreeShakingExportUsage(key, shareItem, shareItem.name, options) : void 0;
3597
3702
  const treeShakingProviderExports = treeShakingUsage?.kind === "exports" ? treeShakingUsage.usedExports : [];
3598
3703
  const treeShakingUsedExports = resolvedOptions.injectTreeShakingUsedExports === false ? treeShakingConfig?.usedExports || [] : treeShakingProviderExports;
@@ -3609,26 +3714,54 @@ function generateLocalSharedImportMap(options) {
3609
3714
  eager: ${Boolean(shareItem.shareConfig.eager)},
3610
3715
  from: ${toSafeJsLiteral(resolvedOptions.name)},
3611
3716
  canLiveRebind: ${canLiveRebind},
3612
- async get () {
3717
+ get () {
3613
3718
  if (${shareItem.shareConfig.import === false}) {
3614
3719
  throw new Error(\`[Module Federation] Shared module '\${${toSafeJsLiteral(key)}}' must be provided by host\`);
3615
3720
  }
3616
- usedShared[${toSafeJsLiteral(key)}].loaded = true
3617
- const {${toSafeJsLiteral(key)}: pkgDynamicImport} = importMap
3618
- const res = await pkgDynamicImport()
3619
- const exportModule = ${toSafeJsLiteral(useDirectReactImport)} && ${toSafeJsLiteral(key)} === "react"
3620
- ? (res?.default ?? res)
3621
- : __mfNormalizeRuntimeShare({...res})
3622
- // All npm packages pre-built by vite will be converted to esm
3623
- if (exportModule.__esModule !== true) {
3624
- Object.defineProperty(exportModule, "__esModule", {
3625
- value: true,
3626
- enumerable: false
3627
- })
3628
- }
3629
- return function () {
3630
- return exportModule
3721
+ // A webpack consumer built with eager: true calls get() synchronously and needs the
3722
+ // factory, not a promise: once the module is loaded, hand the same factory back directly,
3723
+ // and while it is loading hand every caller the same pending promise.
3724
+ const share = usedShared[${toSafeJsLiteral(key)}]
3725
+ if (share.lib) return share.lib
3726
+ if (share.loading) return share.loading
3727
+ const cachedSingleton = ${shareItem.shareConfig.singleton && isReactFamily}
3728
+ ? __mfGetCachedReactFamily(
3729
+ ${toSafeJsLiteral(cacheKeys)},
3730
+ ${toSafeJsLiteral(reactCacheKeys)},
3731
+ ${toSafeJsLiteral(shareItem.version)},
3732
+ ${toSafeJsLiteral(key === "react-dom/client" ? "createRoot" : void 0)}
3733
+ )
3734
+ : undefined
3735
+ if (cachedSingleton !== undefined) {
3736
+ share.lib = function () { return cachedSingleton }
3737
+ share.loaded = true
3738
+ return share.lib
3631
3739
  }
3740
+ share.loading = (async () => {
3741
+ try {
3742
+ const {${toSafeJsLiteral(key)}: pkgDynamicImport} = importMap
3743
+ const res = await pkgDynamicImport()
3744
+ const exportModule = ${toSafeJsLiteral(useDirectReactImport)} && ${toSafeJsLiteral(key)} === "react"
3745
+ ? (res?.default ?? res)
3746
+ : __mfNormalizeRuntimeShare({...res})
3747
+ // All npm packages pre-built by vite will be converted to esm
3748
+ if (exportModule.__esModule !== true) {
3749
+ Object.defineProperty(exportModule, "__esModule", {
3750
+ value: true,
3751
+ enumerable: false
3752
+ })
3753
+ }
3754
+ share.lib = function () {
3755
+ return exportModule
3756
+ }
3757
+ share.loaded = true
3758
+ return share.lib
3759
+ } finally {
3760
+ // A failed import must not pin the rejection: the next get() retries
3761
+ share.loading = undefined
3762
+ }
3763
+ })()
3764
+ return share.loading
3632
3765
  },
3633
3766
  shareConfig: {
3634
3767
  singleton: ${shareItem.shareConfig.singleton},
@@ -4054,10 +4187,26 @@ function generateRuntimeSharedCacheSeedCode(shareStrategy, options) {
4054
4187
  );
4055
4188
  return;
4056
4189
  }
4057
- const pendingExternalProvider = typeof __mfGetPendingExternalSharedProvider === 'function'
4058
- ? __mfGetPendingExternalSharedProvider(pkg, share)
4190
+ const externalProvider = typeof __mfGetExternalSharedProvider === 'function'
4191
+ ? __mfGetExternalSharedProvider(pkg, share)
4059
4192
  : undefined;
4060
- if (pendingExternalProvider && !pendingExternalProvider.lib && !pendingExternalProvider.loaded) {
4193
+ if (externalProvider) {
4194
+ let externalFactory = externalProvider.lib;
4195
+ if (!externalFactory && externalProvider.loading) externalFactory = await externalProvider.loading;
4196
+ if (!externalFactory && externalProvider.loaded && typeof externalProvider.get === 'function') {
4197
+ externalFactory = await externalProvider.get();
4198
+ }
4199
+ if (externalFactory) {
4200
+ const externalModule = typeof externalFactory === "function" ? externalFactory() : externalFactory;
4201
+ const externalResolved = await Promise.resolve(externalModule);
4202
+ ${normalizeRuntimeShareCode}
4203
+ __mfWriteSharedCache(
4204
+ __mfModuleCache.share,
4205
+ cacheDescriptor,
4206
+ __mfNormalizeRuntimeShare(externalResolved),
4207
+ externalProvider.from
4208
+ );
4209
+ }
4061
4210
  return;
4062
4211
  }
4063
4212
  const providerKey = cacheDescriptor.canonical;
@@ -4342,7 +4491,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
4342
4491
  const needsSharedProviderSelectionHelper = Object.keys(options.shared ?? {}).length > 0;
4343
4492
  const hasTreeShakingShared = Object.values(options.shared ?? {}).some((share) => !!share?.shareConfig.treeShaking);
4344
4493
  const hasMultipleShareScopes = Array.isArray(options.shareScope);
4345
- const guardHostAutoInit = command === "build" && Object.keys(options.exposes ?? {}).length > 0 && Object.keys(options.remotes ?? {}).length > 0;
4494
+ const guardHostAutoInit = command === "build" && isRemoteContainer(options) && hasRemotes(options);
4346
4495
  const materializedShareBatches = toSafeJsLiteral(getShareBatches(options, false));
4347
4496
  const runtimeImports = [
4348
4497
  "init as runtimeInit",
@@ -4397,6 +4546,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
4397
4546
  import {${runtimeImports}} from "@module-federation/runtime";
4398
4547
  ${runtimeHelperImports.length ? `import {${runtimeHelperImports.join(", ")}} from "@module-federation/runtime/helpers";` : ""}
4399
4548
  ${pluginImportNames.filter((item) => !isSsrOnlyPlugin(item[1])).map((item) => item[1]).join("\n")}
4549
+ import __mfExposesMap from "${virtualExposesId}"
4400
4550
  ${command === "build" ? getRuntimeInitResolveBootstrapCode(false, getRuntimeInitStatusImportId(options)) : getRuntimeInitBootstrapCode(false, getRuntimeInitStatusImportId(options), void 0, void 0, exportConditions) + "\n const { initResolve } = globalThis[globalKey];"}
4401
4551
  ${getRuntimeModuleCacheBootstrapCode(exportConditions)}
4402
4552
  const initTokens = {}
@@ -4405,7 +4555,6 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
4405
4555
  const mfName = ${toSafeJsLiteral(options.name)}
4406
4556
  const __mfMaterializedShareBatches = ${materializedShareBatches}
4407
4557
  let localSharedImportMapPromise
4408
- let exposesMapPromise
4409
4558
  let __mfLateBridgeShared
4410
4559
  const shouldRetrySharedInitError = ${command !== "build"} && ((error) => {
4411
4560
  const message = String((error && error.message) || error || '');
@@ -4439,12 +4588,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
4439
4588
  }
4440
4589
 
4441
4590
  async function getExposesMap() {
4442
- if (!exposesMapPromise) {
4443
- exposesMapPromise = retrySharedInit(() => import("${virtualExposesId}"))
4444
- .then((mod) => mod.default ?? mod)
4445
- .catch((e) => { exposesMapPromise = undefined; throw e; });
4446
- }
4447
- return exposesMapPromise
4591
+ return __mfExposesMap
4448
4592
  }
4449
4593
 
4450
4594
  async function init(shared = {}, initScope = [], remoteEntryInitOptions = {}) {
@@ -4560,29 +4704,33 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
4560
4704
  const parts = pkg.split('/');
4561
4705
  return pkg.startsWith('@') ? parts.slice(0, 2).join('/') : parts[0];
4562
4706
  };
4563
- const __mfGetPendingExternalSharedProvider = (pkg, share, versionMap) => {
4707
+ const __mfGetExternalSharedProvider = (pkg, share, versionMap, includePackage) => {
4564
4708
  if (typeof __mfSelectExternalSharedProvider !== 'function') return undefined;
4565
4709
  const packageName = __mfGetSharePackageName(pkg);
4566
- const candidates = packageName === pkg
4710
+ const candidates = !includePackage || packageName === pkg
4567
4711
  ? [[pkg, share]]
4568
4712
  : [[pkg, share], [packageName, usedShared[packageName]]];
4569
4713
  for (const [candidatePkg, candidateShare] of candidates) {
4570
4714
  if (!candidateShare) continue;
4571
4715
  const candidateVersionMap = versionMap
4572
4716
  ? (candidatePkg === pkg ? versionMap : initialShared[candidatePkg])
4573
- : ${hasMultipleShareScopes ? "getShareVersions(candidatePkg, candidateShare)" : "shared[candidatePkg]"};
4717
+ : (initialShared[candidatePkg] ?? ${hasMultipleShareScopes ? "getShareVersions(candidatePkg, candidateShare)" : "shared[candidatePkg]"});
4574
4718
  const provider = __mfSelectExternalSharedProvider(
4575
4719
  candidateVersionMap,
4576
4720
  candidatePkg,
4577
4721
  candidateShare,
4578
4722
  '${options.shareStrategy}'
4579
4723
  );
4580
- if (provider && isWebpackProvider(provider) && !provider.lib && !provider.loaded) {
4581
- return provider;
4582
- }
4724
+ if (provider) return provider;
4583
4725
  }
4584
4726
  return undefined;
4585
4727
  };
4728
+ const __mfGetPendingExternalSharedProvider = (pkg, share, versionMap) => {
4729
+ const provider = __mfGetExternalSharedProvider(pkg, share, versionMap, true);
4730
+ return provider && isWebpackProvider(provider) && !provider.lib && !provider.loaded
4731
+ ? provider
4732
+ : undefined;
4733
+ };
4586
4734
  // handling circular init calls before an external provider can re-enter this container
4587
4735
  ${hasMultipleShareScopes ? `const shareScopeNamesToInitialize = [];
4588
4736
  for (const shareScopeName of shareScopeNames) {
@@ -5451,6 +5599,7 @@ function generatePendingSharesCode(command = "build", options) {
5451
5599
  const pendingShareImports = command === "build" ? getMaterializedShares(options).filter((pkg) => {
5452
5600
  const shareItem = getShareItemForPreload(pkg, resolvedOptions);
5453
5601
  if (!shareItem || pkg.endsWith("/")) return false;
5602
+ if (shareItem.shareConfig.eager) return false;
5454
5603
  return shareItem.shareConfig.import !== false && !shareItem.shareConfig.treeShaking;
5455
5604
  }).map((pkg) => `[${toSafeJsLiteral(pkg)}, () => import(${toSafeJsLiteral(getLoadShareModulePath(pkg, false, options))})]`) : [];
5456
5605
  return `
@@ -5793,9 +5942,10 @@ function generateRemotes(id, command, enableSsrInit = false, consumer = "unified
5793
5942
  const devRuntimeBootstrap = `${getRuntimeInitBootstrapCode(enableSsrInit, getRuntimeInitStatusImportId(options), ssrRemotes, hostAutoInitPath, exportConditions)}
5794
5943
  const { initPromise, initResolve, initReject, moduleCache: __mfModuleCache } = globalThis[globalKey];`;
5795
5944
  const importLine = command === "build" ? `${getRuntimeModuleCacheBootstrapCode(exportConditions)}
5796
- import { hostInitPromise as __mfHostInitPromise } from ${JSON.stringify(hostAutoInitPath)};` : `${devRuntimeBootstrap}
5945
+ const __mfHostInitPromise = () => import(${JSON.stringify(hostAutoInitPath)})
5946
+ .then((mod) => mod.hostInitPromise);` : `${devRuntimeBootstrap}
5797
5947
  ${command === "serve" && consumer !== "server" ? browserHostInitCode : ""}`;
5798
- const remoteLoadRuntimePromise = command === "build" ? "__mfHostInitPromise" : "initPromise";
5948
+ const remoteLoadRuntimePromise = command === "build" ? "__mfHostInitPromise()" : "initPromise";
5799
5949
  const remoteCacheKey = `${getRuntimeRemoteCachePrefix(options)}${id}`;
5800
5950
  const remoteLoadFailureHandler = command === "build" ? `.catch((error) => {
5801
5951
  delete __mfModuleCache.remote[pendingKey];
@@ -5859,24 +6009,19 @@ function generateRemotes(id, command, enableSsrInit = false, consumer = "unified
5859
6009
  }
5860
6010
  //#endregion
5861
6011
  //#region src/plugins/pluginAddEntry.ts
5862
- const isPreloadableVirtualMfChunk = (name) => name.includes("virtual_mf") && !name.includes("__prebuild__") && !name.includes("__loadShare__");
6012
+ const isPreloadableVirtualMfChunk = (name) => name.includes("virtual_mf") && !name.includes("__prebuild__") && !name.includes("__loadShare__") && !name.includes("__loadRemote__");
5863
6013
  const HOST_INIT_PRELOAD_CHUNKS = [
5864
6014
  (name) => name === "hostInit",
5865
6015
  (name) => name === "remoteEntry",
5866
- (name) => name === "virtualExposes",
5867
6016
  isPreloadableVirtualMfChunk,
5868
6017
  (name) => name === "index"
5869
6018
  ];
5870
6019
  const isRemoteWarmupExcluded = (name) => name.includes("__prebuild__") || name.includes("__loadShare__");
5871
- const REMOTE_ENTRY_WARMUP_CHUNKS = [
5872
- (name) => name === "hostInit",
5873
- (name) => name === "virtualExposes",
5874
- (name) => isPreloadableVirtualMfChunk(name) && !isRemoteWarmupExcluded(name)
5875
- ];
6020
+ const REMOTE_ENTRY_WARMUP_CHUNKS = [(name) => name === "hostInit", (name) => isPreloadableVirtualMfChunk(name) && !isRemoteWarmupExcluded(name)];
5876
6021
  function getChunksByFileName(bundle) {
5877
6022
  return new Map(Object.values(bundle).filter((chunk) => chunk.type === "chunk").map((chunk) => [chunk.fileName, chunk]));
5878
6023
  }
5879
- function collectPreloadChunkFiles(chunksByFileName, seeds, excludeFromClosure = (name) => name.includes("__prebuild__")) {
6024
+ function collectPreloadChunkFiles(chunksByFileName, seeds, excludeFromClosure = (name) => name.includes(PREBUILD_TAG)) {
5880
6025
  const seenFiles = /* @__PURE__ */ new Set();
5881
6026
  const files = [];
5882
6027
  const queue = [...seeds];
@@ -6081,7 +6226,7 @@ const __mfCurrentScript = document.currentScript;
6081
6226
  const remoteSources = isLoadedFirstClientBuild ? Array.from(getPreloadRemotes(normalizedOptions)) : Object.keys(getUsedRemotesMap(federationOptions));
6082
6227
  return Array.from(new Set(remoteSources.flatMap((remote) => {
6083
6228
  const registration = getRemoteRegistration(remote, normalizedOptions.remotes, federationOptions);
6084
- return registration && (registration.type === "module" || registration.type === "esm") && /^(?:https?:)?\/\//.test(registration.entry) ? [registration.entry] : [];
6229
+ return registration && (registration.type === "module" || registration.type === "esm") && /^(?:https?:)?\/\//.test(registration.entry) && !/\.json(?:[?#]|$)/i.test(registration.entry) ? [registration.entry] : [];
6085
6230
  })));
6086
6231
  }
6087
6232
  function getBootstrapSource(initSrc, entrySrc, useSystemImportFallback = false, options) {
@@ -6109,7 +6254,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
6109
6254
  import(/* @vite-ignore */ __mfRemoteEntryPrefetchUrl).catch(() => {});
6110
6255
  }
6111
6256
  ` : "";
6112
- const sharedPreloadSources = _command === "serve" && waitsForInit && Object.keys(normalizedOptions.exposes || {}).length > 0 && Object.keys(normalizedOptions.remotes || {}).length === 0 && federationOptions ? Array.from(getUsedShares(federationOptions)).filter((pkg) => !pkg.endsWith("/")).filter((pkg) => {
6257
+ const sharedPreloadSources = _command === "serve" && waitsForInit && isRemoteOnlyContainer(normalizedOptions) && federationOptions ? Array.from(getUsedShares(federationOptions)).filter((pkg) => !pkg.endsWith("/")).filter((pkg) => {
6113
6258
  const shareItem = federationOptions.shared[pkg] || Object.entries(federationOptions.shared).find(([key]) => key.endsWith("/") && pkg.startsWith(key))?.[1];
6114
6259
  const isExplicitShare = Object.hasOwn(federationOptions.shared, pkg);
6115
6260
  return shareItem?.shareConfig?.singleton === true && shareItem?.shareConfig?.import !== false && !shareItem?.shareConfig?.treeShaking && (isExplicitShare || typeof shareItem?.shareConfig?.import === "string" || Boolean(getProjectResolvedImportPath(pkg)));
@@ -6195,7 +6340,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
6195
6340
  }
6196
6341
  function isFederationInternalVirtualId(id) {
6197
6342
  const normalized = decodeViteId(id).replace(/^\0+/, "");
6198
- return normalized.includes("virtual:mf:") || /__(?:loadShare|prebuild|loadRemote)__/.test(normalized);
6343
+ return normalized.includes("virtual:mf:") || normalized.startsWith("virtual:mf-") || /__(?:loadShare|prebuild|loadRemote)__/.test(normalized);
6199
6344
  }
6200
6345
  function isWorkspaceSourceId(id) {
6201
6346
  const normalized = normalizeModuleId(decodeViteId(id));
@@ -6334,15 +6479,24 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
6334
6479
  configResolved(config) {
6335
6480
  viteConfig = config;
6336
6481
  skipTransformIds = new Set(skipTransformFor.map(resolveProjectId));
6337
- const ctx = this;
6338
- const envName = ctx != null && typeof ctx === "object" ? ctx["environment"] : void 0;
6339
- if (envName?.name && envName.name !== "client") return;
6340
- const inputOptions = getBuildInput(config);
6482
+ const clientEnvironmentInputs = [];
6483
+ for (const environment of Object.values(config.environments ?? {})) {
6484
+ if (environment.consumer !== "client") continue;
6485
+ const input = getBuildInput(environment);
6486
+ if (!input) {
6487
+ htmlFilePath ??= path$1.resolve(config.root, "index.html");
6488
+ continue;
6489
+ }
6490
+ if (typeof input === "string") clientEnvironmentInputs.push(input);
6491
+ else if (Array.isArray(input)) clientEnvironmentInputs.push(...input);
6492
+ else clientEnvironmentInputs.push(...Object.values(input));
6493
+ }
6494
+ const inputOptions = clientEnvironmentInputs.length > 0 ? clientEnvironmentInputs : getBuildInput(config);
6341
6495
  if (!inputOptions) htmlFilePath = path$1.resolve(config.root, "index.html");
6342
6496
  else if (typeof inputOptions === "string") entryFiles = [resolveProjectId(inputOptions)];
6343
6497
  else if (Array.isArray(inputOptions)) entryFiles = inputOptions.filter((input) => !isReactRouterClientRouteInput(String(input))).map(resolveProjectId);
6344
6498
  else if (typeof inputOptions === "object") entryFiles = Object.values(inputOptions).filter((input) => !isReactRouterClientRouteInput(String(input))).map((input) => resolveProjectId(String(input)));
6345
- if (entryFiles.length > 0) htmlFilePath = getFirstHtmlEntryFile(entryFiles);
6499
+ if (entryFiles.length > 0) htmlFilePath = getFirstHtmlEntryFile(entryFiles) ?? htmlFilePath;
6346
6500
  if (config.command === "serve" && !htmlFilePath) {
6347
6501
  const rootIndexHtml = path$1.resolve(config.root, "index.html");
6348
6502
  if (fs$2.existsSync(rootIndexHtml)) htmlFilePath = rootIndexHtml;
@@ -6457,14 +6611,13 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
6457
6611
  },
6458
6612
  transform(code, id) {
6459
6613
  if (skipSvelteKitSsrBuild()) return;
6614
+ if (viteConfig?.command === "build" && !waitsForInit) return;
6460
6615
  if (isSvelteKitServerModule(id)) return;
6461
6616
  if (hasEntryBootstrapParam(id)) return;
6462
6617
  if (normalizeModuleId(id).endsWith(".html")) return;
6463
6618
  const projectId = resolveProjectId(id);
6464
6619
  if (skipTransformIds.has(projectId)) return;
6465
- const transformCtx = this;
6466
- const transformEnv = transformCtx != null && typeof transformCtx === "object" ? transformCtx["environment"] : void 0;
6467
- if (transformEnv?.name && transformEnv.name !== "client") return;
6620
+ if (!isClientEnvironment(this)) return;
6468
6621
  const isVinext = hasPackageDependency("vinext");
6469
6622
  if (isVinext && inject === "html" && id.includes("virtual:vite-rsc/remove-duplicate-server-css")) {
6470
6623
  const namespaceReactImport = `import * as React from 'react';`;
@@ -7252,7 +7405,7 @@ function pluginExternalRuntimeCore() {
7252
7405
  }
7253
7406
  //#endregion
7254
7407
  //#region package.json
7255
- var version$1 = "1.21.6";
7408
+ var version$1 = "1.22.0";
7256
7409
  //#endregion
7257
7410
  //#region src/virtualModules/index.ts
7258
7411
  function initVirtualModules(command, remoteEntryId, enableSsrInit = false, options) {
@@ -7699,8 +7852,38 @@ function collectImportedCss(chunks) {
7699
7852
  for (const chunk of chunks) for (const cssFile of chunk.viteMetadata?.importedCss ?? []) css.add(cssFile);
7700
7853
  return Array.from(css);
7701
7854
  }
7702
- function expandExposeAssets(filesMap, exposeModules, bundle, remoteEntryFileName, options) {
7855
+ /**
7856
+ * Collects the virtual module ids of the `__loadShare__` wrappers belonging to shares
7857
+ * that are not eager.
7858
+ *
7859
+ * Such a wrapper resolves its share through the host at runtime, so it is a deferred
7860
+ * dependency even though the expose statically imports it. Advertising it as a sync
7861
+ * asset makes a preloader fetch a provider the host is going to supply anyway.
7862
+ */
7863
+ function collectDeferredShareModules(options, isRolldown) {
7864
+ const deferred = /* @__PURE__ */ new Set();
7865
+ for (const shareKey of getUsedShares(options)) {
7866
+ const shareConfig = getNormalizeShareItem(shareKey, options)?.shareConfig;
7867
+ if (shareConfig?.eager === true) continue;
7868
+ if (shareConfig?.import === false) continue;
7869
+ deferred.add(normalizeVirtualModuleId(getLoadShareModulePath(shareKey, isRolldown, options)));
7870
+ }
7871
+ return deferred;
7872
+ }
7873
+ /**
7874
+ * True when the chunk exists to load a deferred share rather than expose code.
7875
+ *
7876
+ * `chunk.moduleIds` carry Rollup's `\0` virtual-module prefix while
7877
+ * `getLoadShareModulePath` returns the unprefixed id, so both sides are normalized —
7878
+ * the same comparison `isContainerBootstrapChunk` makes.
7879
+ */
7880
+ function isDeferredShareChunk(chunk, deferredShareModules) {
7881
+ if (!chunk || chunk.type !== "chunk" || deferredShareModules.size === 0) return false;
7882
+ return [chunk.facadeModuleId, ...chunk.moduleIds ?? []].some((id) => typeof id === "string" && deferredShareModules.has(normalizeVirtualModuleId(id)));
7883
+ }
7884
+ function expandExposeAssets(filesMap, exposeModules, bundle, remoteEntryFileName, options, isRolldown) {
7703
7885
  if (exposeModules.length === 0) return;
7886
+ const deferredShareModules = collectDeferredShareModules(options, isRolldown);
7704
7887
  const containerChunks = remoteEntryFileName ? collectStaticChunks(bundle, [remoteEntryFileName]) : [];
7705
7888
  const bootstrapChunks = containerChunks.slice(1);
7706
7889
  const seen = new Set(containerChunks.map((chunk) => chunk.fileName));
@@ -7721,11 +7904,13 @@ function expandExposeAssets(filesMap, exposeModules, bundle, remoteEntryFileName
7721
7904
  for (const exposeModule of exposeModules) {
7722
7905
  const assets = filesMap[exposeModule];
7723
7906
  if (!assets) continue;
7724
- const syncChunks = collectStaticChunks(bundle, assets.js.sync);
7907
+ const allSyncChunks = collectStaticChunks(bundle, assets.js.sync);
7908
+ const syncChunks = allSyncChunks.filter((chunk) => !isDeferredShareChunk(chunk, deferredShareModules));
7909
+ const deferredChunks = allSyncChunks.filter((chunk) => isDeferredShareChunk(chunk, deferredShareModules));
7725
7910
  const sync = Array.from(/* @__PURE__ */ new Set([...bootstrapAssets, ...syncChunks.map((chunk) => chunk.fileName)]));
7726
7911
  const syncSet = new Set(sync);
7727
- const asyncChunks = collectStaticChunks(bundle, assets.js.async);
7728
- const async = asyncChunks.map((chunk) => chunk.fileName).filter((fileName) => !syncSet.has(fileName));
7912
+ const asyncChunks = [...collectStaticChunks(bundle, assets.js.async), ...deferredChunks];
7913
+ const async = Array.from(new Set(asyncChunks.map((chunk) => chunk.fileName))).filter((fileName) => !syncSet.has(fileName));
7729
7914
  assets.js.sync = sync;
7730
7915
  assets.js.async = async;
7731
7916
  const syncCss = Array.from(/* @__PURE__ */ new Set([
@@ -7901,7 +8086,7 @@ const Manifest = (providedOptions) => {
7901
8086
  root,
7902
8087
  stripKnownJsExtensions: true
7903
8088
  });
7904
- expandExposeAssets(filesMap, exposesModules, bundle, foundRemoteEntryFile, mfOptions);
8089
+ expandExposeAssets(filesMap, exposesModules, bundle, foundRemoteEntryFile, mfOptions, getIsRolldown(this));
7905
8090
  const fileToShareKey = await buildFileToShareKeyMap(getUsedShares(mfOptions), this.resolve.bind(this), mfOptions);
7906
8091
  processModuleAssets(Object.fromEntries(Object.entries(bundle).filter(([, file]) => !isTreeShakingProviderChunk(file))), filesMap, (modulePath) => fileToShareKey.get(modulePath));
7907
8092
  for (const shareKey of getUsedShares(mfOptions)) {
@@ -8438,21 +8623,6 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
8438
8623
  };
8439
8624
  }
8440
8625
  //#endregion
8441
- //#region src/utils/remoteConsumerTarget.ts
8442
- function getPluginEnvironmentName(ctx) {
8443
- if (ctx == null || typeof ctx !== "object") return void 0;
8444
- const environment = ctx["environment"];
8445
- if (environment == null || typeof environment !== "object") return void 0;
8446
- const name = environment["name"];
8447
- return typeof name === "string" ? name : void 0;
8448
- }
8449
- function resolveRemoteConsumer(ctx, hasMultiEnvironment) {
8450
- if (!hasMultiEnvironment) return "unified";
8451
- const envName = getPluginEnvironmentName(ctx);
8452
- if (!envName || envName === "client") return "client";
8453
- return "server";
8454
- }
8455
- //#endregion
8456
8626
  //#region src/plugins/pluginProxyRemotes.ts
8457
8627
  function isNodeModulesImporter(importer) {
8458
8628
  return importer?.includes("/node_modules/") || importer?.includes("\\node_modules\\");
@@ -8755,6 +8925,21 @@ function isSharedPackageDependency(sharedKey, dependency) {
8755
8925
  }
8756
8926
  return reachable.has(dependency);
8757
8927
  }
8928
+ function isConfiguredSharedPackage(pkg, shared) {
8929
+ return Object.keys(shared).some((key) => getPackageName(key) === pkg);
8930
+ }
8931
+ function shouldKeepSharedImportLocal(source, importer, sharedKey, shared, importerPackage) {
8932
+ if (!importer || shared[sharedKey]?.shareConfig.import === false) return false;
8933
+ const prebuildImporter = importer.includes("__prebuild__") ? VirtualModule.findModule(PREBUILD_TAG, importer) : void 0;
8934
+ const fallbackPackage = prebuildImporter ? getPackageName(prebuildImporter.name) : importerPackage;
8935
+ if (!fallbackPackage || !isConfiguredSharedPackage(fallbackPackage, shared)) return false;
8936
+ const sourcePackage = getPackageName(sharedKey);
8937
+ if (fallbackPackage !== "react-dom" || sourcePackage !== "react") return false;
8938
+ if (prebuildImporter && matchesSharedSource(source, prebuildImporter.name)) return false;
8939
+ if (!isSharedPackageDependency(prebuildImporter?.name ?? fallbackPackage, sourcePackage)) return false;
8940
+ if (isSharedPackageDependency(sharedKey, fallbackPackage)) return false;
8941
+ return true;
8942
+ }
8758
8943
  const sharedRuntimeDependencyCache = /* @__PURE__ */ new Map();
8759
8944
  const SOURCE_FILE_RE = /\.(?:[cm]?js|[cm]?ts|jsx|tsx)$/;
8760
8945
  const NON_RUNTIME_SOURCE_RE = /(?:\.d\.[cm]?ts|\.(?:test|spec|stories)\.[cm]?[jt]sx?)$/;
@@ -9124,7 +9309,7 @@ function proxySharedModule(options) {
9124
9309
  if (!key) return;
9125
9310
  const importerPackage = getSharedPackageFromFile(importer, shared);
9126
9311
  if (importerPackage === getPackageName(key)) return;
9127
- if (importerPackage) {
9312
+ if (importerPackage && shared[key].shareConfig.import !== false) {
9128
9313
  const importerIsUnsharedWorkspacePackage = !isNodeModulePath(importer) && !Object.keys(shared).some((sharedKey) => getPackageName(sharedKey) === importerPackage);
9129
9314
  const runtimeDependencyRequest = key.endsWith("/") && matchesSharedSource(source, key) ? source : key;
9130
9315
  if (importerIsUnsharedWorkspacePackage ? isSharedPackageRuntimeDependency(runtimeDependencyRequest, importerPackage, getRuntimeDependencyConditions(this, resolveOptions)) : isSharedPackageDependency(key, importerPackage)) return;
@@ -9138,6 +9323,10 @@ function proxySharedModule(options) {
9138
9323
  if (shouldSkipTaggedImporterProxy(key, "__loadShare__")) return;
9139
9324
  if (shouldSkipTaggedImporterProxy(key, "__prebuild__")) return;
9140
9325
  const shareSource = key === "vue" && source.startsWith("vue/dist/") ? key : isNodeModulePath(source) ? getCommonSharedSubpathFromNodeModulePath(source, key) || key : source;
9326
+ if (shouldKeepSharedImportLocal(source, importer, key, shared, importerPackage)) {
9327
+ const localSource = getPrebuildResolutionSource(shareSource, shared[key]);
9328
+ return tryResolveFromProjectRoot(localSource) || localSource;
9329
+ }
9141
9330
  const loadSharePath = getLoadShareModulePath(shareSource, useRolldown, federationOptions);
9142
9331
  if (!materializedLoadShareSources.has(shareSource)) {
9143
9332
  materializedLoadShareSources.add(shareSource);
@@ -9944,11 +10133,7 @@ var aliasToArrayPlugin_default = {
9944
10133
  };
9945
10134
  //#endregion
9946
10135
  //#region src/utils/controlChunkSanitizer.ts
9947
- const FEDERATION_CONTROL_CHUNK_HINTS = [
9948
- "hostInit",
9949
- "virtualExposes",
9950
- "localSharedImportMap"
9951
- ];
10136
+ const FEDERATION_CONTROL_CHUNK_HINTS = ["hostInit", "localSharedImportMap"];
9952
10137
  function stripEmptyPreloadCalls(code) {
9953
10138
  const helperImportRegex = /import\s*\{\s*_\s*as\s*([A-Za-z_$][\w$]*)\s*\}\s*from\s*["'][^"']+["']\s*;?/g;
9954
10139
  const helperAliases = [];
@@ -10159,7 +10344,7 @@ function escapeUnsafeJsSourceChars(str) {
10159
10344
  }
10160
10345
  function isFederationHtmlPreloadDependency(dep, includeSharedRuntime = false) {
10161
10346
  const file = path$1.basename(dep);
10162
- if (file.includes("__mfe_internal__") || file.includes("virtual_mf-") || file.includes("virtualExposes") || file.includes("localSharedImportMap") || file.includes("hostInit")) return true;
10347
+ if (file.includes("__mfe_internal__") || file.includes("virtual_mf-") || file.includes("localSharedImportMap") || file.includes("hostInit")) return true;
10163
10348
  return includeSharedRuntime && (file.includes("preload-helper") || file.includes("rolldown-runtime") || file.startsWith("dist-"));
10164
10349
  }
10165
10350
  function canResolveSharedSubpath(subpath, projectRoot) {
@@ -10568,9 +10753,7 @@ export default __mfShared.default ?? __mfShared;`
10568
10753
  const automaticJsxRuntime = getAutomaticJsxRuntime(config);
10569
10754
  if (automaticJsxRuntime && materializeAutomaticJsxRuntime(options, automaticJsxRuntime)) writeLocalSharedImportMap(options);
10570
10755
  }
10571
- const viteMajor = parseInt(version, 10);
10572
- const hasRemotes = Object.keys(options.remotes).length > 0;
10573
- if (!getSsrCapabilities(viteMajor, config.command, hasRemotes).injectSsrEntryLoader) return;
10756
+ if (!getSsrCapabilities(parseInt(version, 10), config.command, hasRemotes(options)).injectSsrEntryLoader) return;
10574
10757
  if (options.runtimePlugins.some((p) => {
10575
10758
  return (typeof p === "string" ? p : p[0]) === "@module-federation/vite/ssrEntryLoader";
10576
10759
  })) return;
@@ -10597,7 +10780,10 @@ export default __mfShared.default ?? __mfShared;`
10597
10780
  const ssrEntryLoaderSpecifier = SSR_ENTRY_LOADER_SPECIFIER;
10598
10781
  try {
10599
10782
  resolveImportPath(ssrEntryLoaderSpecifier);
10600
- options.runtimePlugins.push([ssrEntryLoaderSpecifier, { resolvedShared }]);
10783
+ options.runtimePlugins.push([ssrEntryLoaderSpecifier, {
10784
+ resolvedShared,
10785
+ ...options.ssrEntryLoader?.strategy ? { strategy: options.ssrEntryLoader.strategy } : {}
10786
+ }]);
10601
10787
  } catch {}
10602
10788
  }
10603
10789
  };
@@ -10613,7 +10799,7 @@ function applyBuildTimeRuntimeDefines(define, options, { target, isAstro, defaul
10613
10799
  }
10614
10800
  function loadPluginDts(options) {
10615
10801
  if (options.dts === false) return [];
10616
- return [import("./pluginDts-4sHIZPIi.js").then(({ default: pluginDts }) => pluginDts(options))];
10802
+ return [import("./pluginDts-D7Faa4NJ.js").then(({ default: pluginDts }) => pluginDts(options))];
10617
10803
  }
10618
10804
  const INJECT_EXTERNAL_RUNTIME_CORE_PLUGIN = "@module-federation/vite/injectExternalRuntimeCorePlugin";
10619
10805
  function isInjectExternalRuntimeCorePlugin(specifier) {
@@ -10638,7 +10824,6 @@ function resolveInjectExternalRuntimeCorePlugin() {
10638
10824
  function applyExternalRuntimeExperiments(options) {
10639
10825
  const { experiments } = options;
10640
10826
  if (experiments.provideExternalRuntime) {
10641
- if (Object.keys(options.exposes).length > 0) throw createModuleFederationError("You can only set provideExternalRuntime: true in pure consumer which not expose modules.");
10642
10827
  if (!hasInjectExternalRuntimeCorePlugin(options.runtimePlugins)) options.runtimePlugins = options.runtimePlugins.concat(resolveInjectExternalRuntimeCorePlugin());
10643
10828
  }
10644
10829
  }
@@ -10654,7 +10839,7 @@ function federation(mfUserOptions) {
10654
10839
  const virtualExposesId = getVirtualExposesId(options);
10655
10840
  const moduleParseController = createModuleParseController();
10656
10841
  const moduleParsePlugins = pluginModuleParseEnd_default((id) => {
10657
- return id.includes(getHostAutoInitPath(options)) || id.includes(getPendingSharesPath(options)) || id.includes(remoteEntryId) || id.includes(virtualExposesId) || id.includes("virtual:mf-localSharedImportMap") || id.includes("__loadShare__") || id.includes("__prebuild__") || id.includes("__treeShakingProvider__") || id.includes("__mf_tree_shaking_graph__");
10842
+ return id.includes(getHostAutoInitPath(options)) || id.includes(getPendingSharesPath(options)) || id.includes("virtual:mf-REMOTE_ENTRY_ID") || id.includes(virtualExposesId) || id.includes("virtual:mf-localSharedImportMap") || id.includes("__loadShare__") || id.includes("__prebuild__") || id.includes("__treeShakingProvider__") || id.includes("__mf_tree_shaking_graph__");
10658
10843
  }, {
10659
10844
  moduleParseTimeout: options.moduleParseTimeout,
10660
10845
  moduleParseIdleTimeout: options.moduleParseIdleTimeout,
@@ -10829,11 +11014,6 @@ function federation(mfUserOptions) {
10829
11014
  skipTransformFor: Object.values(options.exposes).map((expose) => expose.import),
10830
11015
  federationOptions: options
10831
11016
  }),
10832
- ...addEntry({
10833
- entryName: "virtualExposes",
10834
- entryPath: virtualExposesId,
10835
- federationOptions: options
10836
- }),
10837
11017
  pluginProxyRemoteEntry_default({
10838
11018
  options,
10839
11019
  remoteEntryId,
@@ -10857,6 +11037,10 @@ function federation(mfUserOptions) {
10857
11037
  const runtimeInitId = getRuntimeInitStatusImportId(options);
10858
11038
  config.build = config.build || {};
10859
11039
  if (config.build.modulePreload !== false) {
11040
+ const remoteEntryBasename = path$1.posix.basename(options.filename);
11041
+ const hashParts = remoteEntryBasename.split(/\[hash(?::\d+)?\]/);
11042
+ const remoteEntryFilePattern = new RegExp(`^${hashParts.map((part) => escapeRegExp(part)).join("[\\w-]+")}${hashParts.length > 1 && !/\.[^/.]+$/.test(remoteEntryBasename) ? "\\.js" : ""}$`);
11043
+ const isRemoteEntryFile = (file) => file === remoteEntryBasename || remoteEntryFilePattern.test(file);
10860
11044
  const currentModulePreload = config.build.modulePreload && typeof config.build.modulePreload === "object" ? config.build.modulePreload : {};
10861
11045
  const existingResolveDependencies = currentModulePreload.resolveDependencies;
10862
11046
  config.build.modulePreload = {
@@ -10864,7 +11048,7 @@ function federation(mfUserOptions) {
10864
11048
  resolveDependencies(filename, deps, context) {
10865
11049
  const resolvedDeps = existingResolveDependencies ? existingResolveDependencies(filename, deps, context) : deps;
10866
11050
  const hostFile = path$1.basename(context.hostId);
10867
- if (context.hostType === "js" && (hostFile === options.filename || hostFile.includes("hostInit") || hostFile.includes("virtualExposes") || hostFile.includes("localSharedImportMap"))) return [];
11051
+ if (context.hostType === "js" && (isRemoteEntryFile(hostFile) || hostFile.includes("hostInit") || hostFile.includes("localSharedImportMap"))) return [];
10868
11052
  const hasFederationHtmlDeps = context.hostType === "html" && resolvedDeps.some((dep) => isFederationHtmlPreloadDependency(dep));
10869
11053
  const hasFederationJsDeps = context.hostType === "js" && resolvedDeps.some((dep) => isFederationHtmlPreloadDependency(dep));
10870
11054
  const treeShakingFallbackDeps = hasTreeShakingShared ? (dep) => dep.includes("__prebuild__") : () => false;
@@ -10903,6 +11087,10 @@ function federation(mfUserOptions) {
10903
11087
  const mfChunkName = function(id) {
10904
11088
  if (id.includes(runtimeInitId) || id.includes("__mf_v__runtimeInit__mf_v__")) return "runtimeInit";
10905
11089
  if (id.includes("__loadShare__")) {
11090
+ const pkg = getCachedLoadSharePkg(id);
11091
+ const key = pkg && findSharedKey(pkg, shared);
11092
+ if (useCodeSplitting && key && shared[key].shareConfig.eager === true) return "loadShare-eager";
11093
+ if (key && shared[key].shareConfig.import === false) return null;
10906
11094
  const match = id.match(/([^/\\]+__loadShare__[^/\\]+)/);
10907
11095
  return match ? match[1] : "loadShare";
10908
11096
  }
@@ -11011,8 +11199,8 @@ function federation(mfUserOptions) {
11011
11199
  const virtualModule = VirtualModule.findById(id);
11012
11200
  if (!virtualModule?.code) return null;
11013
11201
  let code = virtualModule.code;
11014
- const environmentName = this.environment?.name;
11015
- if (environmentName && environmentName !== "client" || !environmentName && isSsrBuild) code = prependWorkspaceSingletonSsrImport(code);
11202
+ const consumerTarget = resolveEnvironmentConsumerTarget(this);
11203
+ if (consumerTarget === "server" || !consumerTarget && isSsrBuild) code = prependWorkspaceSingletonSsrImport(code);
11016
11204
  code = code.replace(/import\s+["'][^"']*__prebuild__[^"']*["']\s*;?/g, "");
11017
11205
  code = code.replace(/export\s+\*\s+from\s+["'][^"']*__prebuild__[^"']*["']\s*;?/g, "");
11018
11206
  if (!(/\b(?:var|let|const)\s+__moduleExports\b/.test(code) || /\bexport\s+const\s+__moduleExports\b/.test(code) || /\bexport\s*\{[^}]*__moduleExports/.test(code))) {
@@ -1,5 +1,5 @@
1
1
  import { n as normalizePathForImport } from "./buildPaths-BoaQTkxt.js";
2
- import { _ as mfError, g as createModuleFederationError, l as hasPackageDependency, p as resolveImportPath } from "./dtsConstants-BsaLBaaK.js";
2
+ import { _ as mfError, g as createModuleFederationError, l as hasPackageDependency, p as resolveImportPath } from "./dtsConstants-BEGrtvcw.js";
3
3
  import fs from "fs";
4
4
  import * as path$1 from "node:path";
5
5
  import os from "os";
@@ -470,7 +470,10 @@ async function getSSREntry(remoteEntryUrl, maxAgeMs, fetchTimeoutMs, fetchMaxByt
470
470
  manifestFetchCache.delete(makeUrlCacheKey(getManifestUrl(remoteEntryUrl), fetchTimeoutMs, fetchMaxBytes));
471
471
  const record = setSsrEntryCache(remoteEntryUrl, fetchTimeoutMs, fetchMaxBytes);
472
472
  const next = await record.promise.catch(() => null);
473
- if (previous && next && previous.versionKey !== next.versionKey) dropRemoteCaches(remoteEntryUrl);
473
+ if (previous && next && previous.versionKey !== next.versionKey) {
474
+ dropRemoteCaches(remoteEntryUrl);
475
+ await clearRunnerCaches(remoteEntryUrl);
476
+ }
474
477
  return record.promise;
475
478
  }
476
479
  /**
@@ -490,17 +493,18 @@ function dropRemoteCaches(remoteEntryUrl) {
490
493
  tempFilePathCache.delete(key);
491
494
  }
492
495
  }
493
- function clearRunnerCaches(remoteEntryUrl) {
496
+ async function clearRunnerCaches(remoteEntryUrl) {
494
497
  let remoteOrigin;
495
498
  if (remoteEntryUrl) try {
496
499
  remoteOrigin = new URL(remoteEntryUrl).origin;
497
500
  } catch {
498
501
  return;
499
502
  }
500
- for (const cached of runnerCache.values()) {
501
- if (remoteOrigin && cached.remoteOrigin !== remoteOrigin) continue;
502
- cached.promise.then((runner) => runner?.clearCache?.()).catch(() => {});
503
- }
503
+ await Promise.all([...runnerCache.values()].filter((cached) => !remoteOrigin || cached.remoteOrigin === remoteOrigin).map(async (cached) => {
504
+ try {
505
+ (await cached.promise)?.clearCache?.();
506
+ } catch {}
507
+ }));
504
508
  }
505
509
  /**
506
510
  * Drop the loader's caches so the next `loadEntry` re-resolves and re-fetches
@@ -662,7 +666,7 @@ async function importTempModule(filePath, versionKey) {
662
666
  }
663
667
  let warnedVmUnavailable = false;
664
668
  async function tryVmStrategy(ssrEntry, options) {
665
- const { loadViaVmStrategy, isVmStrategyAvailable } = await import("./ssrVmStrategy-CkmYR5_u.js");
669
+ const { loadViaVmStrategy, isVmStrategyAvailable } = await import("./ssrVmStrategy-Cx9WlTsx.js");
666
670
  if (!await isVmStrategyAvailable()) {
667
671
  if (!warnedVmUnavailable) {
668
672
  warnedVmUnavailable = true;
@@ -1,5 +1,5 @@
1
1
  import { t as findSharedKey } from "./sharedKeyMatcher-DiUzRVH1.js";
2
- import { c as readResponseTextBounded, n as neutralizeBrowserPreloadHelpers, s as fetchWithTimeout, t as SsrEntryHttpError } from "./ssrEntryLoader-BqzV2t-n.js";
2
+ import { c as readResponseTextBounded, n as neutralizeBrowserPreloadHelpers, s as fetchWithTimeout, t as SsrEntryHttpError } from "./ssrEntryLoader-CMVCDSsG.js";
3
3
  //#region src/utils/ssrVmStrategy.ts
4
4
  /**
5
5
  * vm.SourceTextModule strategy for loading remote SSR entries.
@@ -1,2 +1,2 @@
1
- import { i as ssrEntryLoaderPlugin, n as neutralizeBrowserPreloadHelpers, r as revalidate, t as SsrEntryHttpError } from "../ssrEntryLoader-BqzV2t-n.js";
1
+ import { i as ssrEntryLoaderPlugin, n as neutralizeBrowserPreloadHelpers, r as revalidate, t as SsrEntryHttpError } from "../ssrEntryLoader-CMVCDSsG.js";
2
2
  export { SsrEntryHttpError, ssrEntryLoaderPlugin as default, neutralizeBrowserPreloadHelpers, revalidate };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@module-federation/vite",
3
- "version": "1.21.6",
3
+ "version": "1.22.0",
4
4
  "description": "Vite plugin for Module Federation",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",