@module-federation/vite 1.12.1-next.1 → 1.12.2

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/lib/index.cjs CHANGED
@@ -58,6 +58,7 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry" }) => {
58
58
  let _command;
59
59
  let emitFileId;
60
60
  let viteConfig;
61
+ let clientInjected = false;
61
62
  function injectHtml() {
62
63
  return inject === "html" && htmlFilePath;
63
64
  }
@@ -88,6 +89,7 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry" }) => {
88
89
  },
89
90
  transformIndexHtml(c) {
90
91
  if (!injectHtml()) return;
92
+ clientInjected = true;
91
93
  return c.replace("<head>", `<head><script type="module" src=${JSON.stringify(devEntryPath.replace(/.+?\:([/\\])[/\\]?/, "$1").replace(/\\\\?/g, "/"))}><\/script>`);
92
94
  },
93
95
  transform(code, id) {
@@ -160,9 +162,10 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry" }) => {
160
162
  }
161
163
  },
162
164
  transform(code, id) {
163
- if (injectEntry() && entryFiles.some((file) => id.endsWith(file))) return mapCodeToCodeWithSourcemap(`
164
- import ${JSON.stringify(getEntryPath())};
165
- ` + code);
165
+ if (injectEntry() && entryFiles.some((file) => id.endsWith(file)) || _command === "serve" && inject === "html" && !clientInjected && !id.includes("node_modules") && /\.(js|ts|mjs|vue|jsx|tsx)(\?|$)/.test(id)) {
166
+ clientInjected = true;
167
+ return mapCodeToCodeWithSourcemap(`import ${JSON.stringify(getEntryPath())};\n` + code);
168
+ }
166
169
  }
167
170
  }];
168
171
  };
@@ -856,10 +859,14 @@ var VirtualModule = class {
856
859
  writeSync(code, force) {
857
860
  if (!force && this.inited) return;
858
861
  if (!this.inited) this.inited = true;
859
- (0, fs.writeFileSync)(this.getPath(), code);
862
+ const path = this.getPath();
863
+ (0, fs.mkdirSync)((0, pathe.dirname)(path), { recursive: true });
864
+ (0, fs.writeFileSync)(path, code);
860
865
  }
861
866
  write(code) {
862
- (0, fs.writeFile)(this.getPath(), code, function() {});
867
+ const path = this.getPath();
868
+ (0, fs.mkdirSync)((0, pathe.dirname)(path), { recursive: true });
869
+ (0, fs.writeFile)(path, code, function() {});
863
870
  }
864
871
  };
865
872
  //#endregion
@@ -907,6 +914,14 @@ if (!globalThis[globalKey]) {
907
914
  initResolve,
908
915
  initReject,
909
916
  };
917
+ // In SSR (no window), resolve immediately with a stub runtime
918
+ // so modules don't hang waiting for browser-only init
919
+ if (typeof window === 'undefined') {
920
+ initResolve({
921
+ loadRemote: function() { return Promise.resolve(undefined); },
922
+ loadShare: function() { return Promise.resolve(undefined); },
923
+ });
924
+ }
910
925
  }
911
926
  ${exportStatement}
912
927
  `);
@@ -957,7 +972,7 @@ function generateRemotes(id, command, isRolldown) {
957
972
  function getPackageNamedExports(pkg) {
958
973
  try {
959
974
  const mod = (0, module$1.createRequire)(new URL("file://" + process.cwd() + "/package.json"))(pkg);
960
- return Object.keys(mod).filter((k) => k !== "default" && k !== "__esModule");
975
+ return Object.keys(mod).filter((k) => k !== "default" && k !== "__esModule" && /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(k));
961
976
  } catch {
962
977
  return [];
963
978
  }
@@ -986,9 +1001,9 @@ function writeLoadShareModule(pkg, shareItem, command, isRolldown) {
986
1001
  const namedExports = getPackageNamedExports(pkg);
987
1002
  let exportLine;
988
1003
  if (namedExports.length > 0) {
989
- const destructure = `const { ${namedExports.join(", ")} } = exportModule;`;
990
- const namedExportLine = `export { ${namedExports.join(", ")} };`;
991
- exportLine = useESM ? `export default exportModule;\n ${destructure}\n ${namedExportLine}` : `module.exports = exportModule;\n ${destructure}\n Object.assign(module.exports, { ${namedExports.join(", ")} });`;
1004
+ const destructure = `const { ${namedExports.map((name, i) => `${name}: __mf_${i}`).join(", ")} } = exportModule;`;
1005
+ const namedExportLine = `export { ${namedExports.map((name, i) => `__mf_${i} as ${name}`).join(", ")} };`;
1006
+ exportLine = useESM ? `export default exportModule;\n ${destructure}\n ${namedExportLine}` : `module.exports = exportModule;\n ${destructure}\n Object.assign(module.exports, { ${namedExports.map((name, i) => `"${name}": __mf_${i}`).join(", ")} });`;
992
1007
  } else exportLine = useESM ? `export default exportModule\n export * from ${JSON.stringify(getPreBuildLibImportId(pkg))}` : "module.exports = exportModule";
993
1008
  loadShareCacheMap[pkg].writeSync(`
994
1009
  import ${JSON.stringify(getPreBuildLibImportId(pkg))};
@@ -1657,14 +1672,16 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
1657
1672
  const host = typeof viteConfig.server?.host === "string" && viteConfig.server.host !== "0.0.0.0" ? viteConfig.server.host : "localhost";
1658
1673
  const publicPath = JSON.stringify(resolvePublicPath(options, viteConfig.base) + options.filename);
1659
1674
  return `
1660
- const origin = (window && ${!options.ignoreOrigin}) ? window.origin : "//${host}:${viteConfig.server?.port}"
1661
- const remoteEntryPromise = await import(origin + ${publicPath})
1662
- // __tla only serves as a hack for vite-plugin-top-level-await.
1663
- Promise.resolve(remoteEntryPromise)
1664
- .then(remoteEntry => {
1665
- return Promise.resolve(remoteEntry.__tla)
1666
- .then(remoteEntry.init).catch(remoteEntry.init)
1667
- })
1675
+ if (typeof window !== 'undefined') {
1676
+ const origin = (${!options.ignoreOrigin}) ? window.origin : "//${host}:${viteConfig.server?.port}"
1677
+ const remoteEntryPromise = await import(origin + ${publicPath})
1678
+ // __tla only serves as a hack for vite-plugin-top-level-await.
1679
+ Promise.resolve(remoteEntryPromise)
1680
+ .then(remoteEntry => {
1681
+ return Promise.resolve(remoteEntry.__tla)
1682
+ .then(remoteEntry.init).catch(remoteEntry.init)
1683
+ })
1684
+ }
1668
1685
  `;
1669
1686
  }
1670
1687
  return code;
@@ -1926,13 +1943,13 @@ function createEarlyVirtualModulesPlugin(options) {
1926
1943
  name: "vite:module-federation-early-init",
1927
1944
  enforce: "pre",
1928
1945
  config(config, { command: _command }) {
1929
- if (_command !== "serve") return;
1930
- const isRolldown = !!this?.meta?.rolldownVersion;
1931
1946
  const root = config.root || process.cwd();
1932
1947
  initVirtualModuleInfrastructure(root, virtualModuleDir);
1933
1948
  VirtualModule.setRoot(root);
1934
1949
  VirtualModule.ensureVirtualPackageExists();
1935
1950
  initVirtualModules(_command, getRemoteEntryId(options));
1951
+ if (_command !== "serve") return;
1952
+ const isRolldown = !!this?.meta?.rolldownVersion;
1936
1953
  if (remotes && Object.keys(remotes).length > 0) for (const key of Object.keys(remotes)) addUsedRemote(key, key);
1937
1954
  if (shared && Object.keys(shared).length > 0) {
1938
1955
  config.optimizeDeps = config.optimizeDeps || {};
@@ -2206,6 +2223,9 @@ function federation(mfUserOptions) {
2206
2223
  config.optimizeDeps.include ||= [];
2207
2224
  config.optimizeDeps.include.push("@module-federation/runtime");
2208
2225
  config.optimizeDeps.include.push(virtualDir);
2226
+ config.ssr ||= {};
2227
+ config.ssr.noExternal ||= [];
2228
+ if (Array.isArray(config.ssr.noExternal)) config.ssr.noExternal.push(virtualDir);
2209
2229
  options.runtimePlugins.forEach((p) => {
2210
2230
  const pluginPath = typeof p === "string" ? p : p[0];
2211
2231
  if (pluginPath && !pluginPath.startsWith(".") && !pluginPath.startsWith("/") && !pluginPath.startsWith("\0") && !pluginPath.startsWith("virtual:")) config.optimizeDeps.include.push(pluginPath);
package/lib/index.mjs CHANGED
@@ -37,6 +37,7 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry" }) => {
37
37
  let _command;
38
38
  let emitFileId;
39
39
  let viteConfig;
40
+ let clientInjected = false;
40
41
  function injectHtml() {
41
42
  return inject === "html" && htmlFilePath;
42
43
  }
@@ -67,6 +68,7 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry" }) => {
67
68
  },
68
69
  transformIndexHtml(c) {
69
70
  if (!injectHtml()) return;
71
+ clientInjected = true;
70
72
  return c.replace("<head>", `<head><script type="module" src=${JSON.stringify(devEntryPath.replace(/.+?\:([/\\])[/\\]?/, "$1").replace(/\\\\?/g, "/"))}><\/script>`);
71
73
  },
72
74
  transform(code, id) {
@@ -139,9 +141,10 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry" }) => {
139
141
  }
140
142
  },
141
143
  transform(code, id) {
142
- if (injectEntry() && entryFiles.some((file) => id.endsWith(file))) return mapCodeToCodeWithSourcemap(`
143
- import ${JSON.stringify(getEntryPath())};
144
- ` + code);
144
+ if (injectEntry() && entryFiles.some((file) => id.endsWith(file)) || _command === "serve" && inject === "html" && !clientInjected && !id.includes("node_modules") && /\.(js|ts|mjs|vue|jsx|tsx)(\?|$)/.test(id)) {
145
+ clientInjected = true;
146
+ return mapCodeToCodeWithSourcemap(`import ${JSON.stringify(getEntryPath())};\n` + code);
147
+ }
145
148
  }
146
149
  }];
147
150
  };
@@ -834,10 +837,14 @@ var VirtualModule = class {
834
837
  writeSync(code, force) {
835
838
  if (!force && this.inited) return;
836
839
  if (!this.inited) this.inited = true;
837
- writeFileSync(this.getPath(), code);
840
+ const path = this.getPath();
841
+ mkdirSync(dirname(path), { recursive: true });
842
+ writeFileSync(path, code);
838
843
  }
839
844
  write(code) {
840
- writeFile(this.getPath(), code, function() {});
845
+ const path = this.getPath();
846
+ mkdirSync(dirname(path), { recursive: true });
847
+ writeFile(path, code, function() {});
841
848
  }
842
849
  };
843
850
  //#endregion
@@ -885,6 +892,14 @@ if (!globalThis[globalKey]) {
885
892
  initResolve,
886
893
  initReject,
887
894
  };
895
+ // In SSR (no window), resolve immediately with a stub runtime
896
+ // so modules don't hang waiting for browser-only init
897
+ if (typeof window === 'undefined') {
898
+ initResolve({
899
+ loadRemote: function() { return Promise.resolve(undefined); },
900
+ loadShare: function() { return Promise.resolve(undefined); },
901
+ });
902
+ }
888
903
  }
889
904
  ${exportStatement}
890
905
  `);
@@ -935,7 +950,7 @@ function generateRemotes(id, command, isRolldown) {
935
950
  function getPackageNamedExports(pkg) {
936
951
  try {
937
952
  const mod = createRequire$1(new URL("file://" + process.cwd() + "/package.json"))(pkg);
938
- return Object.keys(mod).filter((k) => k !== "default" && k !== "__esModule");
953
+ return Object.keys(mod).filter((k) => k !== "default" && k !== "__esModule" && /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(k));
939
954
  } catch {
940
955
  return [];
941
956
  }
@@ -964,9 +979,9 @@ function writeLoadShareModule(pkg, shareItem, command, isRolldown) {
964
979
  const namedExports = getPackageNamedExports(pkg);
965
980
  let exportLine;
966
981
  if (namedExports.length > 0) {
967
- const destructure = `const { ${namedExports.join(", ")} } = exportModule;`;
968
- const namedExportLine = `export { ${namedExports.join(", ")} };`;
969
- exportLine = useESM ? `export default exportModule;\n ${destructure}\n ${namedExportLine}` : `module.exports = exportModule;\n ${destructure}\n Object.assign(module.exports, { ${namedExports.join(", ")} });`;
982
+ const destructure = `const { ${namedExports.map((name, i) => `${name}: __mf_${i}`).join(", ")} } = exportModule;`;
983
+ const namedExportLine = `export { ${namedExports.map((name, i) => `__mf_${i} as ${name}`).join(", ")} };`;
984
+ exportLine = useESM ? `export default exportModule;\n ${destructure}\n ${namedExportLine}` : `module.exports = exportModule;\n ${destructure}\n Object.assign(module.exports, { ${namedExports.map((name, i) => `"${name}": __mf_${i}`).join(", ")} });`;
970
985
  } else exportLine = useESM ? `export default exportModule\n export * from ${JSON.stringify(getPreBuildLibImportId(pkg))}` : "module.exports = exportModule";
971
986
  loadShareCacheMap[pkg].writeSync(`
972
987
  import ${JSON.stringify(getPreBuildLibImportId(pkg))};
@@ -1635,14 +1650,16 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
1635
1650
  const host = typeof viteConfig.server?.host === "string" && viteConfig.server.host !== "0.0.0.0" ? viteConfig.server.host : "localhost";
1636
1651
  const publicPath = JSON.stringify(resolvePublicPath(options, viteConfig.base) + options.filename);
1637
1652
  return `
1638
- const origin = (window && ${!options.ignoreOrigin}) ? window.origin : "//${host}:${viteConfig.server?.port}"
1639
- const remoteEntryPromise = await import(origin + ${publicPath})
1640
- // __tla only serves as a hack for vite-plugin-top-level-await.
1641
- Promise.resolve(remoteEntryPromise)
1642
- .then(remoteEntry => {
1643
- return Promise.resolve(remoteEntry.__tla)
1644
- .then(remoteEntry.init).catch(remoteEntry.init)
1645
- })
1653
+ if (typeof window !== 'undefined') {
1654
+ const origin = (${!options.ignoreOrigin}) ? window.origin : "//${host}:${viteConfig.server?.port}"
1655
+ const remoteEntryPromise = await import(origin + ${publicPath})
1656
+ // __tla only serves as a hack for vite-plugin-top-level-await.
1657
+ Promise.resolve(remoteEntryPromise)
1658
+ .then(remoteEntry => {
1659
+ return Promise.resolve(remoteEntry.__tla)
1660
+ .then(remoteEntry.init).catch(remoteEntry.init)
1661
+ })
1662
+ }
1646
1663
  `;
1647
1664
  }
1648
1665
  return code;
@@ -1904,13 +1921,13 @@ function createEarlyVirtualModulesPlugin(options) {
1904
1921
  name: "vite:module-federation-early-init",
1905
1922
  enforce: "pre",
1906
1923
  config(config, { command: _command }) {
1907
- if (_command !== "serve") return;
1908
- const isRolldown = !!this?.meta?.rolldownVersion;
1909
1924
  const root = config.root || process.cwd();
1910
1925
  initVirtualModuleInfrastructure(root, virtualModuleDir);
1911
1926
  VirtualModule.setRoot(root);
1912
1927
  VirtualModule.ensureVirtualPackageExists();
1913
1928
  initVirtualModules(_command, getRemoteEntryId(options));
1929
+ if (_command !== "serve") return;
1930
+ const isRolldown = !!this?.meta?.rolldownVersion;
1914
1931
  if (remotes && Object.keys(remotes).length > 0) for (const key of Object.keys(remotes)) addUsedRemote(key, key);
1915
1932
  if (shared && Object.keys(shared).length > 0) {
1916
1933
  config.optimizeDeps = config.optimizeDeps || {};
@@ -2184,6 +2201,9 @@ function federation(mfUserOptions) {
2184
2201
  config.optimizeDeps.include ||= [];
2185
2202
  config.optimizeDeps.include.push("@module-federation/runtime");
2186
2203
  config.optimizeDeps.include.push(virtualDir);
2204
+ config.ssr ||= {};
2205
+ config.ssr.noExternal ||= [];
2206
+ if (Array.isArray(config.ssr.noExternal)) config.ssr.noExternal.push(virtualDir);
2187
2207
  options.runtimePlugins.forEach((p) => {
2188
2208
  const pluginPath = typeof p === "string" ? p : p[0];
2189
2209
  if (pluginPath && !pluginPath.startsWith(".") && !pluginPath.startsWith("/") && !pluginPath.startsWith("\0") && !pluginPath.startsWith("virtual:")) config.optimizeDeps.include.push(pluginPath);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@module-federation/vite",
3
- "version": "1.12.1-next.1",
3
+ "version": "1.12.2",
4
4
  "description": "Vite plugin for Module Federation",
5
5
  "type": "module",
6
6
  "main": "./lib/index.cjs",
@@ -87,4 +87,4 @@
87
87
  "vite": "^7.3.1",
88
88
  "vitest": "^4.0.18"
89
89
  }
90
- }
90
+ }