@module-federation/vite 1.18.0 → 1.18.1

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.
Files changed (2) hide show
  1. package/lib/index.js +69 -14
  2. package/package.json +4 -4
package/lib/index.js CHANGED
@@ -2184,7 +2184,14 @@ const WORKSPACE_SINGLETON_SSR_LOCAL_SHARE = "__mfNormalizeShareModule(__mfLocalS
2184
2184
  function prependWorkspaceSingletonSsrImport(code) {
2185
2185
  if (!code.includes("if (import.meta.env.SSR)")) return code;
2186
2186
  if (!code.includes(WORKSPACE_SINGLETON_SSR_LOCAL_SHARE)) return code;
2187
- if (code.includes("import * as __mfLocalShare")) return code;
2187
+ const localShareImport = /^[ \t]*import\s+\*\s+as\s+__mfLocalShare\s+from\s+(['"])(.+?)\1\s*;?[ \t]*\r?\n?/gm;
2188
+ let hasLocalShareImport = false;
2189
+ code = code.replace(localShareImport, (statement) => {
2190
+ if (hasLocalShareImport) return "";
2191
+ hasLocalShareImport = true;
2192
+ return statement;
2193
+ });
2194
+ if (hasLocalShareImport) return code;
2188
2195
  const importMatch = code.match(/initPromise\.then\(\(\)\s*=>\s*\{[\s\S]*?\breturn import\((["'])(.+?)\1\)\.then\(\(mod\)\s*=>\s*\{[\s\S]*?__mfApplyLazyShareExports/) ?? code.match(/initPromise\.then\(\(\)\s*=>\s*\n\s*import\((["'])(.+?)\1\)\.then\(\(mod\)\s*=>\s*\{[\s\S]*?__mfApplyLazyShareExports/) ?? code.match(/import\((["'])(.+?)\1\)/);
2189
2196
  if (!importMatch) return code;
2190
2197
  const quote = importMatch[1];
@@ -2347,7 +2354,7 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
2347
2354
  initBlock = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
2348
2355
  __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});`;
2349
2356
  }
2350
- const prebuildImportLine = usesDeferredSingletonFallback || usesDeferredTreeShakingFallback ? servesRemoteSingletonFallback || usesDeferredSingletonFallback && command !== "build" && (isWorkspaceSingleton || isWorkspacePackage) ? `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(lazyLocalFallbackSource)};` : "" : `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(detectedNamedExports === void 0 ? coherentLocalSource : skipServePrebuildWarmup ? devImportSource : sharedImportSource)};`;
2357
+ const prebuildImportLine = usesEagerWorkspaceFallback || usesEntryInjectedRemoteFallback ? "" : usesDeferredSingletonFallback || usesDeferredTreeShakingFallback ? servesRemoteSingletonFallback || usesDeferredSingletonFallback && command !== "build" && (isWorkspaceSingleton || isWorkspacePackage) ? `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(lazyLocalFallbackSource)};` : "" : `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(detectedNamedExports === void 0 ? coherentLocalSource : skipServePrebuildWarmup ? devImportSource : sharedImportSource)};`;
2351
2358
  const devDynamicImportLine = isWorkspacePackage ? "" : usesDeferredSingletonFallback || usesDeferredTreeShakingFallback ? "" : command !== "build" && !skipServePrebuildWarmup ? `;() => import(${escapeGeneratedStringLiteral(devImportSource)}).catch(() => {});` : "";
2352
2359
  const moduleBody = usesDeferredSingletonFallback || usesDeferredTreeShakingFallback ? `
2353
2360
  ${prebuildImportLine}
@@ -7025,11 +7032,27 @@ function pluginRemoteNamedExports(options) {
7025
7032
  //#endregion
7026
7033
  //#region src/plugins/pluginSSRRemoteEntry.ts
7027
7034
  const MAX_RUNNER_BODY_BYTES = 1024 * 1024;
7035
+ const MAX_RUNNER_START_OFFSET = 1024 * 1024;
7028
7036
  const ALLOWED_RUNNER_INVOKE_NAMES = new Set(["fetchModule", "getBuiltins"]);
7029
7037
  const VITE_FS_PREFIX = "/@fs/";
7030
7038
  function isPlainObject(value) {
7031
7039
  return !!value && typeof value === "object" && !Array.isArray(value);
7032
7040
  }
7041
+ function isSafeRunnerFetchModuleOptions(value) {
7042
+ if (!isPlainObject(value)) return false;
7043
+ const allowedKeys = new Set([
7044
+ "cached",
7045
+ "startOffset",
7046
+ "inlineSourceMap"
7047
+ ]);
7048
+ for (const [key, option] of Object.entries(value)) {
7049
+ if (!allowedKeys.has(key)) return false;
7050
+ if (key === "startOffset") {
7051
+ if (typeof option !== "number" || !Number.isSafeInteger(option) || option < 0 || option > MAX_RUNNER_START_OFFSET) return false;
7052
+ } else if (typeof option !== "boolean") return false;
7053
+ }
7054
+ return true;
7055
+ }
7033
7056
  function stripQueryAndHash(id) {
7034
7057
  const queryIndex = id.indexOf("?");
7035
7058
  const hashIndex = id.indexOf("#");
@@ -7067,9 +7090,8 @@ function isPathWithinAllowedDirectories(filePath, allowedDirectories) {
7067
7090
  }
7068
7091
  function isSafeRunnerFetchModuleId(id, config) {
7069
7092
  if (typeof id !== "string" || !id) return false;
7070
- const rawDecoded = decodeViteId(id);
7071
- const decoded = rawDecoded.replace(/^\0+/, "");
7072
- if (!decoded || rawDecoded.startsWith("\0") || decoded.startsWith("virtual:")) return !!decoded;
7093
+ const decoded = decodeViteId(id).replace(/^\0+/, "");
7094
+ if (!decoded || decoded.startsWith("virtual:")) return !!decoded;
7073
7095
  if (decoded.startsWith("file://")) try {
7074
7096
  const filePath = decodeURIComponent(new URL(decoded).pathname);
7075
7097
  return path$1.isAbsolute(filePath) && isPathWithinAllowedDirectories(filePath, getRunnerAllowedDirectories(config));
@@ -7101,7 +7123,7 @@ function isRunnerInvokePayload(payload, config) {
7101
7123
  if (name === "getBuiltins") return args.length === 0;
7102
7124
  if (args.length < 1 || args.length > 3) return false;
7103
7125
  const [id, importer, opts] = args;
7104
- return isSafeRunnerFetchModuleId(id, config) && (importer === void 0 || importer === null || isSafeRunnerFetchModuleId(importer, config)) && (opts === void 0 || isPlainObject(opts));
7126
+ return isSafeRunnerFetchModuleId(id, config) && (importer === void 0 || importer === null || isSafeRunnerFetchModuleId(importer, config)) && (opts === void 0 || isSafeRunnerFetchModuleOptions(opts));
7105
7127
  }
7106
7128
  function readBoundedRunnerBody(req, res) {
7107
7129
  return new Promise((resolve) => {
@@ -7217,14 +7239,6 @@ function pluginSSRRemoteEntry(options) {
7217
7239
  const clientEnv = server.environments?.client;
7218
7240
  const runnerEnv = typeof ssrEnv?.hot?.handleInvoke === "function" ? ssrEnv : typeof clientEnv?.hot?.handleInvoke === "function" ? clientEnv : void 0;
7219
7241
  if (typeof (ssrEnv?.fetchModule ?? clientEnv?.fetchModule) === "function" && runnerEnv) server.middlewares.use("/__mf_runner__", async (req, res) => {
7220
- res.setHeader("Access-Control-Allow-Origin", "*");
7221
- if (req.method === "OPTIONS") {
7222
- res.setHeader("Access-Control-Allow-Methods", "POST");
7223
- res.setHeader("Access-Control-Allow-Headers", "Content-Type");
7224
- res.statusCode = 204;
7225
- res.end();
7226
- return;
7227
- }
7228
7242
  if (req.method !== "POST") {
7229
7243
  res.statusCode = 405;
7230
7244
  res.end("Method not allowed");
@@ -7655,6 +7669,43 @@ function canResolveSharedSubpath(subpath, projectRoot) {
7655
7669
  }
7656
7670
  }
7657
7671
  /**
7672
+ * Vite's dependency scanner cannot see through the virtual loadShare modules
7673
+ * generated for shared packages. As a result, dependencies of a linked/shared
7674
+ * package may be discovered one request at a time and each discovery starts a
7675
+ * new optimizer pass. Seed the optimizer with the complete dependency graph
7676
+ * before the first request instead.
7677
+ *
7678
+ * Vite then resolves the package's own dependency graph using its normal
7679
+ * scanner, preserving package and peer-dependency resolution semantics.
7680
+ */
7681
+ function includeLinkedSharedEntries(optimizeDeps, shared, projectRoot, exposes, outDir) {
7682
+ const additions = /* @__PURE__ */ new Set();
7683
+ const entries = new Set(Array.isArray(optimizeDeps.entries) ? optimizeDeps.entries : optimizeDeps.entries ? [optimizeDeps.entries] : [
7684
+ "**/*.html",
7685
+ "!**/node_modules/**",
7686
+ `!**/${outDir.replace(/\\/g, "/")}/**`,
7687
+ "!**/__tests__/**",
7688
+ "!**/coverage/**"
7689
+ ]);
7690
+ for (const [packageName, share] of Object.entries(shared ?? {})) {
7691
+ if (share?.shareConfig?.import === false) continue;
7692
+ const installed = getInstalledPackageJson(packageName, { cwd: projectRoot });
7693
+ if (!installed || installed.dir.replaceAll("\\", "/").includes("/node_modules/")) continue;
7694
+ const entry = getInstalledPackageEntry(packageName, { cwd: projectRoot });
7695
+ if (entry && existsSync(entry)) additions.add(entry);
7696
+ }
7697
+ for (const expose of Object.values(exposes ?? {})) {
7698
+ const source = expose.import;
7699
+ if (source.startsWith(".") || path$1.isAbsolute(source)) {
7700
+ const entry = path$1.resolve(projectRoot, source);
7701
+ if (existsSync(entry)) additions.add(entry);
7702
+ }
7703
+ }
7704
+ if (additions.size === 0) return;
7705
+ for (const entry of additions) entries.add(entry);
7706
+ optimizeDeps.entries = [...entries];
7707
+ }
7708
+ /**
7658
7709
  * Plugin that runs FIRST to register generated virtual modules in the config hook.
7659
7710
  * This prevents 504 "Outdated Optimize Dep" errors by ensuring ids are known
7660
7711
  * before Vite's optimization phase.
@@ -7818,6 +7869,10 @@ export default __mfShared.default ?? __mfShared;`
7818
7869
  }
7819
7870
  writeLocalSharedImportMap();
7820
7871
  }
7872
+ if (_command === "serve") {
7873
+ config.optimizeDeps ??= {};
7874
+ includeLinkedSharedEntries(config.optimizeDeps, shared, root, options.exposes, config.build?.outDir ?? "dist");
7875
+ }
7821
7876
  },
7822
7877
  configResolved(config) {
7823
7878
  const viteMajor = parseInt(version, 10);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@module-federation/vite",
3
- "version": "1.18.0",
3
+ "version": "1.18.1",
4
4
  "description": "Vite plugin for Module Federation",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -70,9 +70,9 @@
70
70
  "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
71
71
  },
72
72
  "dependencies": {
73
- "@module-federation/dts-plugin": "2.7.0",
74
- "@module-federation/runtime": "2.7.0",
75
- "@module-federation/sdk": "2.7.0"
73
+ "@module-federation/dts-plugin": "2.8.0",
74
+ "@module-federation/runtime": "2.8.0",
75
+ "@module-federation/sdk": "2.8.0"
76
76
  },
77
77
  "devDependencies": {
78
78
  "@playwright/test": "1.58.2",