@module-federation/vite 1.8.1 → 1.9.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
@@ -109,6 +109,15 @@ export default defineConfig({
109
109
  },
110
110
  filename: "remoteEntry.js",
111
111
  shared: ["vue"],
112
+ // Optional parameter that controls where the host initialization script is injected.
113
+ // By default, it is injected into the index.html file.
114
+ // You can set this to "entry" to inject it into the entry script instead.
115
+ // Useful if your application does not load from index.html.
116
+ hostInitInjectLocation: "html", // or "entry"
117
+ // Controls whether all CSS assets from the bundle should be added to every exposed module.
118
+ // When false (default), the plugin will not process any CSS assets.
119
+ // When true, all CSS assets are bundled into every exposed module.
120
+ bundleAllCSS: false, // or true
112
121
  }),
113
122
  ],
114
123
  server: {
@@ -124,6 +133,7 @@ export default defineConfig({
124
133
  ```
125
134
 
126
135
  The host app configuration specifies its name, the filename of its exposed remote entry remoteEntry.js, and importantly, the configuration of the remote application to load.
136
+ You can specify the place the host initialization file is injected with the **hostInitInjectLocation** option, which is described in the example code above.
127
137
 
128
138
  ## Load the Remote App
129
139
 
package/lib/index.cjs CHANGED
@@ -1,9 +1,9 @@
1
1
  var defu = require('defu');
2
2
  var fs = require('fs');
3
3
  var path = require('pathe');
4
+ var MagicString = require('magic-string');
4
5
  var pluginutils = require('@rollup/pluginutils');
5
6
  var estreeWalker = require('estree-walker');
6
- var MagicString = require('magic-string');
7
7
 
8
8
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
9
9
 
@@ -31,6 +31,21 @@ var path__namespace = /*#__PURE__*/_interopNamespace(path);
31
31
  var path__default = /*#__PURE__*/_interopDefaultLegacy(path);
32
32
  var MagicString__default = /*#__PURE__*/_interopDefaultLegacy(MagicString);
33
33
 
34
+ var mapCodeToCodeWithSourcemap = function mapCodeToCodeWithSourcemap(code) {
35
+ return Promise.resolve(code).then(function (resolvedCode) {
36
+ if (resolvedCode === undefined) {
37
+ return;
38
+ }
39
+ var s = new MagicString__default["default"](resolvedCode);
40
+ return {
41
+ code: s.toString(),
42
+ map: s.generateMap({
43
+ hires: true
44
+ })
45
+ };
46
+ });
47
+ };
48
+
34
49
  function getFirstHtmlEntryFile(entryFiles) {
35
50
  return entryFiles.find(function (file) {
36
51
  return file.endsWith('.html');
@@ -150,7 +165,7 @@ var addEntry = function addEntry(_ref) {
150
165
  return id.endsWith(file);
151
166
  })) {
152
167
  var injection = "\n import " + JSON.stringify(entryPath) + ";\n ";
153
- return injection + code;
168
+ return mapCodeToCodeWithSourcemap(injection + code);
154
169
  }
155
170
  }
156
171
  }];
@@ -383,6 +398,7 @@ function normalizeShareItem(key, shareItem) {
383
398
  scope: 'default',
384
399
  from: '',
385
400
  shareConfig: {
401
+ "import": undefined,
386
402
  singleton: false,
387
403
  requiredVersion: version ? "^" + version : '*'
388
404
  }
@@ -394,6 +410,7 @@ function normalizeShareItem(key, shareItem) {
394
410
  version: shareItem.version || version,
395
411
  scope: shareItem.shareScope || 'default',
396
412
  shareConfig: {
413
+ "import": typeof shareItem === 'object' ? shareItem["import"] : undefined,
397
414
  singleton: shareItem.singleton || false,
398
415
  requiredVersion: shareItem.requiredVersion || (version ? "^" + version : '*'),
399
416
  strictVersion: !!shareItem.strictVersion
@@ -468,7 +485,9 @@ function normalizeModuleFederationOptions(options) {
468
485
  publicPath: options.publicPath,
469
486
  shareStrategy: options.shareStrategy || 'version-first',
470
487
  ignoreOrigin: options.ignoreOrigin || false,
471
- virtualModuleDir: options.virtualModuleDir || '__mf__virtual'
488
+ virtualModuleDir: options.virtualModuleDir || '__mf__virtual',
489
+ hostInitInjectLocation: options.hostInitInjectLocation || 'html',
490
+ bundleAllCSS: options.bundleAllCSS || false
472
491
  };
473
492
  }
474
493
 
@@ -732,12 +751,13 @@ function writeLocalSharedImportMap() {
732
751
  }
733
752
  function generateLocalSharedImportMap() {
734
753
  var options = getNormalizeModuleFederationOptions();
735
- return "\n const importMap = {\n " + Array.from(getUsedShares()).sort().map(function (pkg) {
736
- return "\n " + JSON.stringify(pkg) + ": async () => {\n let pkg = await import(\"" + getPreBuildLibImportId(pkg) + "\")\n return pkg\n }\n ";
754
+ return "\n import {loadShare} from \"@module-federation/runtime\";\n const importMap = {\n " + Array.from(getUsedShares()).sort().map(function (pkg) {
755
+ var shareItem = getNormalizeShareItem(pkg);
756
+ return "\n " + JSON.stringify(pkg) + ": async () => {\n " + ((shareItem == null ? void 0 : shareItem.shareConfig["import"]) === false ? "throw new Error(`Shared module '${" + JSON.stringify(pkg) + "}' must be provided by host`);" : "let pkg = await import(\"" + getPreBuildLibImportId(pkg) + "\");\n return pkg;") + "\n }\n ";
737
757
  }).join(',') + "\n }\n const usedShared = {\n " + Array.from(getUsedShares()).sort().map(function (key) {
738
758
  var shareItem = getNormalizeShareItem(key);
739
759
  if (!shareItem) return null;
740
- return "\n " + JSON.stringify(key) + ": {\n name: " + JSON.stringify(key) + ",\n version: " + JSON.stringify(shareItem.version) + ",\n scope: [" + JSON.stringify(shareItem.scope) + "],\n loaded: false,\n from: " + JSON.stringify(options.name) + ",\n async get () {\n usedShared[" + JSON.stringify(key) + "].loaded = true\n const {" + JSON.stringify(key) + ": pkgDynamicImport} = importMap \n const res = await pkgDynamicImport()\n const exportModule = {...res}\n // All npm packages pre-built by vite will be converted to esm\n Object.defineProperty(exportModule, \"__esModule\", {\n value: true,\n enumerable: false\n })\n return function () {\n return exportModule\n }\n },\n shareConfig: {\n singleton: " + shareItem.shareConfig.singleton + ",\n requiredVersion: " + JSON.stringify(shareItem.shareConfig.requiredVersion) + "\n }\n }\n ";
760
+ return "\n " + JSON.stringify(key) + ": {\n name: " + JSON.stringify(key) + ",\n version: " + JSON.stringify(shareItem.version) + ",\n scope: [" + JSON.stringify(shareItem.scope) + "],\n loaded: false,\n from: " + JSON.stringify(options.name) + ",\n async get () {\n if (" + (shareItem.shareConfig["import"] === false) + ") {\n throw new Error(`Shared module '${" + JSON.stringify(key) + "}' must be provided by host`);\n }\n usedShared[" + JSON.stringify(key) + "].loaded = true\n const {" + JSON.stringify(key) + ": pkgDynamicImport} = importMap\n const res = await pkgDynamicImport()\n const exportModule = {...res}\n // All npm packages pre-built by vite will be converted to esm\n Object.defineProperty(exportModule, \"__esModule\", {\n value: true,\n enumerable: false\n })\n return function () {\n return exportModule\n }\n },\n shareConfig: {\n singleton: " + shareItem.shareConfig.singleton + ",\n requiredVersion: " + JSON.stringify(shareItem.shareConfig.requiredVersion) + ",\n " + (shareItem.shareConfig["import"] === false ? 'import: false,' : '') + "\n }\n }\n ";
741
761
  }).filter(function (x) {
742
762
  return x !== null;
743
763
  }).join(',') + "\n }\n const usedRemotes = [" + Object.keys(getUsedRemotesMap()).map(function (key) {
@@ -767,7 +787,7 @@ function generateRemoteEntry(options) {
767
787
  var HOST_AUTO_INIT_TAG = '__H_A_I__';
768
788
  var hostAutoInitModule = new VirtualModule('hostAutoInit', HOST_AUTO_INIT_TAG);
769
789
  function writeHostAutoInit() {
770
- hostAutoInitModule.writeSync("\n const remoteEntryPromise = import(\"" + REMOTE_ENTRY_ID + "\")\n // __tla only serves as a hack for vite-plugin-top-level-await. \n Promise.resolve(remoteEntryPromise)\n .then(remoteEntry => {\n return Promise.resolve(remoteEntry.__tla)\n .then(remoteEntry.init).catch(remoteEntry.init)\n })\n ");
790
+ hostAutoInitModule.writeSync("\n const remoteEntryPromise = import(\"" + REMOTE_ENTRY_ID + "\")\n // __tla only serves as a hack for vite-plugin-top-level-await.\n Promise.resolve(remoteEntryPromise)\n .then(remoteEntry => {\n return Promise.resolve(remoteEntry.__tla)\n .then(remoteEntry.init).catch(remoteEntry.init)\n })\n ");
771
791
  }
772
792
  function getHostAutoInitImportId() {
773
793
  return hostAutoInitModule.getImportId();
@@ -1092,7 +1112,7 @@ var Manifest = function Manifest() {
1092
1112
  }
1093
1113
  }
1094
1114
  // Second pass: Collect all CSS assets
1095
- var allCssAssets = collectCssAssets(bundle);
1115
+ var allCssAssets = mfOptions.bundleAllCSS ? collectCssAssets(bundle) : new Set();
1096
1116
  var exposesModules = Object.keys(mfOptions.exposes).map(function (item) {
1097
1117
  return mfOptions.exposes[item]["import"];
1098
1118
  });
@@ -1120,8 +1140,10 @@ var Manifest = function Manifest() {
1120
1140
  processModuleAssets(bundle, filesMap, function (modulePath) {
1121
1141
  return fileToShareKey.get(modulePath);
1122
1142
  });
1123
- // Add all CSS assets to every export
1124
- addCssAssetsToAllExports(filesMap, allCssAssets);
1143
+ // Add all CSS assets to every export if bundleAllCSS is enabled
1144
+ if (mfOptions.bundleAllCSS) {
1145
+ addCssAssetsToAllExports(filesMap, allCssAssets);
1146
+ }
1125
1147
  // Final deduplication of all assets
1126
1148
  filesMap = deduplicateAssets(filesMap);
1127
1149
  _this.emitFile({
@@ -1320,15 +1342,15 @@ function pluginProxyRemoteEntry () {
1320
1342
  }
1321
1343
  },
1322
1344
  transform: function transform(code, id) {
1323
- try {
1324
- if (!filter(id)) return Promise.resolve();
1345
+ var transformedCode = function () {
1346
+ if (!filter(id)) return;
1325
1347
  if (id.includes(REMOTE_ENTRY_ID)) {
1326
- return Promise.resolve(parsePromise.then(function (_) {
1348
+ return parsePromise.then(function (_) {
1327
1349
  return generateRemoteEntry(getNormalizeModuleFederationOptions());
1328
- }));
1350
+ });
1329
1351
  }
1330
1352
  if (id === VIRTUAL_EXPOSES) {
1331
- return Promise.resolve(generateExposes());
1353
+ return generateExposes();
1332
1354
  }
1333
1355
  if (id.includes(getHostAutoInitPath())) {
1334
1356
  var options = getNormalizeModuleFederationOptions();
@@ -1336,14 +1358,12 @@ function pluginProxyRemoteEntry () {
1336
1358
  var _viteConfig$server, _viteConfig$server2;
1337
1359
  var host = typeof ((_viteConfig$server = viteConfig.server) == null ? void 0 : _viteConfig$server.host) === 'string' && viteConfig.server.host !== '0.0.0.0' ? viteConfig.server.host : 'localhost';
1338
1360
  var publicPath = JSON.stringify(resolvePublicPath(options, viteConfig.base) + options.filename);
1339
- return Promise.resolve("\n const origin = (window && " + !options.ignoreOrigin + ") ? window.origin : \"//" + host + ":" + ((_viteConfig$server2 = viteConfig.server) == null ? void 0 : _viteConfig$server2.port) + "\"\n const remoteEntryPromise = await import(origin + " + publicPath + ")\n // __tla only serves as a hack for vite-plugin-top-level-await.\n Promise.resolve(remoteEntryPromise)\n .then(remoteEntry => {\n return Promise.resolve(remoteEntry.__tla)\n .then(remoteEntry.init).catch(remoteEntry.init)\n })\n ");
1361
+ return "\n const origin = (window && " + !options.ignoreOrigin + ") ? window.origin : \"//" + host + ":" + ((_viteConfig$server2 = viteConfig.server) == null ? void 0 : _viteConfig$server2.port) + "\"\n const remoteEntryPromise = await import(origin + " + publicPath + ")\n // __tla only serves as a hack for vite-plugin-top-level-await.\n Promise.resolve(remoteEntryPromise)\n .then(remoteEntry => {\n return Promise.resolve(remoteEntry.__tla)\n .then(remoteEntry.init).catch(remoteEntry.init)\n })\n ";
1340
1362
  }
1341
- return Promise.resolve(code);
1363
+ return code;
1342
1364
  }
1343
- return Promise.resolve();
1344
- } catch (e) {
1345
- return Promise.reject(e);
1346
- }
1365
+ }();
1366
+ return mapCodeToCodeWithSourcemap(transformedCode);
1347
1367
  }
1348
1368
  };
1349
1369
  }
@@ -1422,11 +1442,11 @@ function proxySharedModule(options) {
1422
1442
  });
1423
1443
  }
1424
1444
  },
1425
- transform: function transform(code, id) {
1445
+ transform: function transform(_, id) {
1426
1446
  if (id.includes(getLocalSharedImportMapPath())) {
1427
- return parsePromise.then(function (_) {
1447
+ return mapCodeToCodeWithSourcemap(parsePromise.then(function (_) {
1428
1448
  return generateLocalSharedImportMap();
1429
- });
1449
+ }));
1430
1450
  }
1431
1451
  }
1432
1452
  }, {
@@ -1533,7 +1553,8 @@ function federation(mfUserOptions) {
1533
1553
  var options = normalizeModuleFederationOptions(mfUserOptions);
1534
1554
  var name = options.name,
1535
1555
  shared = options.shared,
1536
- filename = options.filename;
1556
+ filename = options.filename,
1557
+ hostInitInjectLocation = options.hostInitInjectLocation;
1537
1558
  if (!name) throw new Error('name is required');
1538
1559
  return [{
1539
1560
  name: 'vite:module-federation-config',
@@ -1552,7 +1573,7 @@ function federation(mfUserOptions) {
1552
1573
  }), addEntry({
1553
1574
  entryName: 'hostInit',
1554
1575
  entryPath: getHostAutoInitPath(),
1555
- inject: 'html'
1576
+ inject: hostInitInjectLocation
1556
1577
  }), addEntry({
1557
1578
  entryName: 'virtualExposes',
1558
1579
  entryPath: VIRTUAL_EXPOSES
package/lib/index.esm.js CHANGED
@@ -3,9 +3,24 @@ import * as fs from 'fs';
3
3
  import { mkdirSync, writeFileSync, existsSync, writeFile } from 'fs';
4
4
  import * as path from 'pathe';
5
5
  import path__default, { resolve, basename, parse, join, dirname } from 'pathe';
6
+ import MagicString from 'magic-string';
6
7
  import { createFilter } from '@rollup/pluginutils';
7
8
  import { walk } from 'estree-walker';
8
- import MagicString from 'magic-string';
9
+
10
+ var mapCodeToCodeWithSourcemap = function mapCodeToCodeWithSourcemap(code) {
11
+ return Promise.resolve(code).then(function (resolvedCode) {
12
+ if (resolvedCode === undefined) {
13
+ return;
14
+ }
15
+ var s = new MagicString(resolvedCode);
16
+ return {
17
+ code: s.toString(),
18
+ map: s.generateMap({
19
+ hires: true
20
+ })
21
+ };
22
+ });
23
+ };
9
24
 
10
25
  function getFirstHtmlEntryFile(entryFiles) {
11
26
  return entryFiles.find(function (file) {
@@ -126,7 +141,7 @@ var addEntry = function addEntry(_ref) {
126
141
  return id.endsWith(file);
127
142
  })) {
128
143
  var injection = "\n import " + JSON.stringify(entryPath) + ";\n ";
129
- return injection + code;
144
+ return mapCodeToCodeWithSourcemap(injection + code);
130
145
  }
131
146
  }
132
147
  }];
@@ -359,6 +374,7 @@ function normalizeShareItem(key, shareItem) {
359
374
  scope: 'default',
360
375
  from: '',
361
376
  shareConfig: {
377
+ "import": undefined,
362
378
  singleton: false,
363
379
  requiredVersion: version ? "^" + version : '*'
364
380
  }
@@ -370,6 +386,7 @@ function normalizeShareItem(key, shareItem) {
370
386
  version: shareItem.version || version,
371
387
  scope: shareItem.shareScope || 'default',
372
388
  shareConfig: {
389
+ "import": typeof shareItem === 'object' ? shareItem["import"] : undefined,
373
390
  singleton: shareItem.singleton || false,
374
391
  requiredVersion: shareItem.requiredVersion || (version ? "^" + version : '*'),
375
392
  strictVersion: !!shareItem.strictVersion
@@ -444,7 +461,9 @@ function normalizeModuleFederationOptions(options) {
444
461
  publicPath: options.publicPath,
445
462
  shareStrategy: options.shareStrategy || 'version-first',
446
463
  ignoreOrigin: options.ignoreOrigin || false,
447
- virtualModuleDir: options.virtualModuleDir || '__mf__virtual'
464
+ virtualModuleDir: options.virtualModuleDir || '__mf__virtual',
465
+ hostInitInjectLocation: options.hostInitInjectLocation || 'html',
466
+ bundleAllCSS: options.bundleAllCSS || false
448
467
  };
449
468
  }
450
469
 
@@ -708,12 +727,13 @@ function writeLocalSharedImportMap() {
708
727
  }
709
728
  function generateLocalSharedImportMap() {
710
729
  var options = getNormalizeModuleFederationOptions();
711
- return "\n const importMap = {\n " + Array.from(getUsedShares()).sort().map(function (pkg) {
712
- return "\n " + JSON.stringify(pkg) + ": async () => {\n let pkg = await import(\"" + getPreBuildLibImportId(pkg) + "\")\n return pkg\n }\n ";
730
+ return "\n import {loadShare} from \"@module-federation/runtime\";\n const importMap = {\n " + Array.from(getUsedShares()).sort().map(function (pkg) {
731
+ var shareItem = getNormalizeShareItem(pkg);
732
+ return "\n " + JSON.stringify(pkg) + ": async () => {\n " + ((shareItem == null ? void 0 : shareItem.shareConfig["import"]) === false ? "throw new Error(`Shared module '${" + JSON.stringify(pkg) + "}' must be provided by host`);" : "let pkg = await import(\"" + getPreBuildLibImportId(pkg) + "\");\n return pkg;") + "\n }\n ";
713
733
  }).join(',') + "\n }\n const usedShared = {\n " + Array.from(getUsedShares()).sort().map(function (key) {
714
734
  var shareItem = getNormalizeShareItem(key);
715
735
  if (!shareItem) return null;
716
- return "\n " + JSON.stringify(key) + ": {\n name: " + JSON.stringify(key) + ",\n version: " + JSON.stringify(shareItem.version) + ",\n scope: [" + JSON.stringify(shareItem.scope) + "],\n loaded: false,\n from: " + JSON.stringify(options.name) + ",\n async get () {\n usedShared[" + JSON.stringify(key) + "].loaded = true\n const {" + JSON.stringify(key) + ": pkgDynamicImport} = importMap \n const res = await pkgDynamicImport()\n const exportModule = {...res}\n // All npm packages pre-built by vite will be converted to esm\n Object.defineProperty(exportModule, \"__esModule\", {\n value: true,\n enumerable: false\n })\n return function () {\n return exportModule\n }\n },\n shareConfig: {\n singleton: " + shareItem.shareConfig.singleton + ",\n requiredVersion: " + JSON.stringify(shareItem.shareConfig.requiredVersion) + "\n }\n }\n ";
736
+ return "\n " + JSON.stringify(key) + ": {\n name: " + JSON.stringify(key) + ",\n version: " + JSON.stringify(shareItem.version) + ",\n scope: [" + JSON.stringify(shareItem.scope) + "],\n loaded: false,\n from: " + JSON.stringify(options.name) + ",\n async get () {\n if (" + (shareItem.shareConfig["import"] === false) + ") {\n throw new Error(`Shared module '${" + JSON.stringify(key) + "}' must be provided by host`);\n }\n usedShared[" + JSON.stringify(key) + "].loaded = true\n const {" + JSON.stringify(key) + ": pkgDynamicImport} = importMap\n const res = await pkgDynamicImport()\n const exportModule = {...res}\n // All npm packages pre-built by vite will be converted to esm\n Object.defineProperty(exportModule, \"__esModule\", {\n value: true,\n enumerable: false\n })\n return function () {\n return exportModule\n }\n },\n shareConfig: {\n singleton: " + shareItem.shareConfig.singleton + ",\n requiredVersion: " + JSON.stringify(shareItem.shareConfig.requiredVersion) + ",\n " + (shareItem.shareConfig["import"] === false ? 'import: false,' : '') + "\n }\n }\n ";
717
737
  }).filter(function (x) {
718
738
  return x !== null;
719
739
  }).join(',') + "\n }\n const usedRemotes = [" + Object.keys(getUsedRemotesMap()).map(function (key) {
@@ -743,7 +763,7 @@ function generateRemoteEntry(options) {
743
763
  var HOST_AUTO_INIT_TAG = '__H_A_I__';
744
764
  var hostAutoInitModule = new VirtualModule('hostAutoInit', HOST_AUTO_INIT_TAG);
745
765
  function writeHostAutoInit() {
746
- hostAutoInitModule.writeSync("\n const remoteEntryPromise = import(\"" + REMOTE_ENTRY_ID + "\")\n // __tla only serves as a hack for vite-plugin-top-level-await. \n Promise.resolve(remoteEntryPromise)\n .then(remoteEntry => {\n return Promise.resolve(remoteEntry.__tla)\n .then(remoteEntry.init).catch(remoteEntry.init)\n })\n ");
766
+ hostAutoInitModule.writeSync("\n const remoteEntryPromise = import(\"" + REMOTE_ENTRY_ID + "\")\n // __tla only serves as a hack for vite-plugin-top-level-await.\n Promise.resolve(remoteEntryPromise)\n .then(remoteEntry => {\n return Promise.resolve(remoteEntry.__tla)\n .then(remoteEntry.init).catch(remoteEntry.init)\n })\n ");
747
767
  }
748
768
  function getHostAutoInitImportId() {
749
769
  return hostAutoInitModule.getImportId();
@@ -1068,7 +1088,7 @@ var Manifest = function Manifest() {
1068
1088
  }
1069
1089
  }
1070
1090
  // Second pass: Collect all CSS assets
1071
- var allCssAssets = collectCssAssets(bundle);
1091
+ var allCssAssets = mfOptions.bundleAllCSS ? collectCssAssets(bundle) : new Set();
1072
1092
  var exposesModules = Object.keys(mfOptions.exposes).map(function (item) {
1073
1093
  return mfOptions.exposes[item]["import"];
1074
1094
  });
@@ -1096,8 +1116,10 @@ var Manifest = function Manifest() {
1096
1116
  processModuleAssets(bundle, filesMap, function (modulePath) {
1097
1117
  return fileToShareKey.get(modulePath);
1098
1118
  });
1099
- // Add all CSS assets to every export
1100
- addCssAssetsToAllExports(filesMap, allCssAssets);
1119
+ // Add all CSS assets to every export if bundleAllCSS is enabled
1120
+ if (mfOptions.bundleAllCSS) {
1121
+ addCssAssetsToAllExports(filesMap, allCssAssets);
1122
+ }
1101
1123
  // Final deduplication of all assets
1102
1124
  filesMap = deduplicateAssets(filesMap);
1103
1125
  _this.emitFile({
@@ -1296,15 +1318,15 @@ function pluginProxyRemoteEntry () {
1296
1318
  }
1297
1319
  },
1298
1320
  transform: function transform(code, id) {
1299
- try {
1300
- if (!filter(id)) return Promise.resolve();
1321
+ var transformedCode = function () {
1322
+ if (!filter(id)) return;
1301
1323
  if (id.includes(REMOTE_ENTRY_ID)) {
1302
- return Promise.resolve(parsePromise.then(function (_) {
1324
+ return parsePromise.then(function (_) {
1303
1325
  return generateRemoteEntry(getNormalizeModuleFederationOptions());
1304
- }));
1326
+ });
1305
1327
  }
1306
1328
  if (id === VIRTUAL_EXPOSES) {
1307
- return Promise.resolve(generateExposes());
1329
+ return generateExposes();
1308
1330
  }
1309
1331
  if (id.includes(getHostAutoInitPath())) {
1310
1332
  var options = getNormalizeModuleFederationOptions();
@@ -1312,14 +1334,12 @@ function pluginProxyRemoteEntry () {
1312
1334
  var _viteConfig$server, _viteConfig$server2;
1313
1335
  var host = typeof ((_viteConfig$server = viteConfig.server) == null ? void 0 : _viteConfig$server.host) === 'string' && viteConfig.server.host !== '0.0.0.0' ? viteConfig.server.host : 'localhost';
1314
1336
  var publicPath = JSON.stringify(resolvePublicPath(options, viteConfig.base) + options.filename);
1315
- return Promise.resolve("\n const origin = (window && " + !options.ignoreOrigin + ") ? window.origin : \"//" + host + ":" + ((_viteConfig$server2 = viteConfig.server) == null ? void 0 : _viteConfig$server2.port) + "\"\n const remoteEntryPromise = await import(origin + " + publicPath + ")\n // __tla only serves as a hack for vite-plugin-top-level-await.\n Promise.resolve(remoteEntryPromise)\n .then(remoteEntry => {\n return Promise.resolve(remoteEntry.__tla)\n .then(remoteEntry.init).catch(remoteEntry.init)\n })\n ");
1337
+ return "\n const origin = (window && " + !options.ignoreOrigin + ") ? window.origin : \"//" + host + ":" + ((_viteConfig$server2 = viteConfig.server) == null ? void 0 : _viteConfig$server2.port) + "\"\n const remoteEntryPromise = await import(origin + " + publicPath + ")\n // __tla only serves as a hack for vite-plugin-top-level-await.\n Promise.resolve(remoteEntryPromise)\n .then(remoteEntry => {\n return Promise.resolve(remoteEntry.__tla)\n .then(remoteEntry.init).catch(remoteEntry.init)\n })\n ";
1316
1338
  }
1317
- return Promise.resolve(code);
1339
+ return code;
1318
1340
  }
1319
- return Promise.resolve();
1320
- } catch (e) {
1321
- return Promise.reject(e);
1322
- }
1341
+ }();
1342
+ return mapCodeToCodeWithSourcemap(transformedCode);
1323
1343
  }
1324
1344
  };
1325
1345
  }
@@ -1398,11 +1418,11 @@ function proxySharedModule(options) {
1398
1418
  });
1399
1419
  }
1400
1420
  },
1401
- transform: function transform(code, id) {
1421
+ transform: function transform(_, id) {
1402
1422
  if (id.includes(getLocalSharedImportMapPath())) {
1403
- return parsePromise.then(function (_) {
1423
+ return mapCodeToCodeWithSourcemap(parsePromise.then(function (_) {
1404
1424
  return generateLocalSharedImportMap();
1405
- });
1425
+ }));
1406
1426
  }
1407
1427
  }
1408
1428
  }, {
@@ -1509,7 +1529,8 @@ function federation(mfUserOptions) {
1509
1529
  var options = normalizeModuleFederationOptions(mfUserOptions);
1510
1530
  var name = options.name,
1511
1531
  shared = options.shared,
1512
- filename = options.filename;
1532
+ filename = options.filename,
1533
+ hostInitInjectLocation = options.hostInitInjectLocation;
1513
1534
  if (!name) throw new Error('name is required');
1514
1535
  return [{
1515
1536
  name: 'vite:module-federation-config',
@@ -1528,7 +1549,7 @@ function federation(mfUserOptions) {
1528
1549
  }), addEntry({
1529
1550
  entryName: 'hostInit',
1530
1551
  entryPath: getHostAutoInitPath(),
1531
- inject: 'html'
1552
+ inject: hostInitInjectLocation
1532
1553
  }), addEntry({
1533
1554
  entryName: 'virtualExposes',
1534
1555
  entryPath: VIRTUAL_EXPOSES
@@ -3,9 +3,23 @@ import * as fs from 'fs';
3
3
  import { mkdirSync, writeFileSync, existsSync, writeFile } from 'fs';
4
4
  import * as path from 'pathe';
5
5
  import path__default, { resolve, basename, parse, join, dirname } from 'pathe';
6
+ import MagicString from 'magic-string';
6
7
  import { createFilter } from '@rollup/pluginutils';
7
8
  import { walk } from 'estree-walker';
8
- import MagicString from 'magic-string';
9
+
10
+ async function mapCodeToCodeWithSourcemap(code) {
11
+ const resolvedCode = await code;
12
+ if (resolvedCode === undefined) {
13
+ return;
14
+ }
15
+ const s = new MagicString(resolvedCode);
16
+ return {
17
+ code: s.toString(),
18
+ map: s.generateMap({
19
+ hires: true
20
+ })
21
+ };
22
+ }
9
23
 
10
24
  function getFirstHtmlEntryFile(entryFiles) {
11
25
  return entryFiles.find(file => file.endsWith('.html'));
@@ -127,7 +141,7 @@ const addEntry = ({
127
141
  const injection = `
128
142
  import ${JSON.stringify(entryPath)};
129
143
  `;
130
- return injection + code;
144
+ return mapCodeToCodeWithSourcemap(injection + code);
131
145
  }
132
146
  }
133
147
  }];
@@ -332,6 +346,7 @@ function normalizeShareItem(key, shareItem) {
332
346
  scope: 'default',
333
347
  from: '',
334
348
  shareConfig: {
349
+ import: undefined,
335
350
  singleton: false,
336
351
  requiredVersion: version ? `^${version}` : '*'
337
352
  }
@@ -343,6 +358,7 @@ function normalizeShareItem(key, shareItem) {
343
358
  version: shareItem.version || version,
344
359
  scope: shareItem.shareScope || 'default',
345
360
  shareConfig: {
361
+ import: typeof shareItem === 'object' ? shareItem.import : undefined,
346
362
  singleton: shareItem.singleton || false,
347
363
  requiredVersion: shareItem.requiredVersion || (version ? `^${version}` : '*'),
348
364
  strictVersion: !!shareItem.strictVersion
@@ -414,7 +430,9 @@ function normalizeModuleFederationOptions(options) {
414
430
  publicPath: options.publicPath,
415
431
  shareStrategy: options.shareStrategy || 'version-first',
416
432
  ignoreOrigin: options.ignoreOrigin || false,
417
- virtualModuleDir: options.virtualModuleDir || '__mf__virtual'
433
+ virtualModuleDir: options.virtualModuleDir || '__mf__virtual',
434
+ hostInitInjectLocation: options.hostInitInjectLocation || 'html',
435
+ bundleAllCSS: options.bundleAllCSS || false
418
436
  };
419
437
  }
420
438
 
@@ -712,13 +730,17 @@ function writeLocalSharedImportMap() {
712
730
  function generateLocalSharedImportMap() {
713
731
  const options = getNormalizeModuleFederationOptions();
714
732
  return `
733
+ import {loadShare} from "@module-federation/runtime";
715
734
  const importMap = {
716
- ${Array.from(getUsedShares()).sort().map(pkg => `
735
+ ${Array.from(getUsedShares()).sort().map(pkg => {
736
+ const shareItem = getNormalizeShareItem(pkg);
737
+ return `
717
738
  ${JSON.stringify(pkg)}: async () => {
718
- let pkg = await import("${getPreBuildLibImportId(pkg)}")
719
- return pkg
739
+ ${(shareItem == null ? void 0 : shareItem.shareConfig.import) === false ? `throw new Error(\`Shared module '\${${JSON.stringify(pkg)}}' must be provided by host\`);` : `let pkg = await import("${getPreBuildLibImportId(pkg)}");
740
+ return pkg;`}
720
741
  }
721
- `).join(',')}
742
+ `;
743
+ }).join(',')}
722
744
  }
723
745
  const usedShared = {
724
746
  ${Array.from(getUsedShares()).sort().map(key => {
@@ -732,8 +754,11 @@ function generateLocalSharedImportMap() {
732
754
  loaded: false,
733
755
  from: ${JSON.stringify(options.name)},
734
756
  async get () {
757
+ if (${shareItem.shareConfig.import === false}) {
758
+ throw new Error(\`Shared module '\${${JSON.stringify(key)}}' must be provided by host\`);
759
+ }
735
760
  usedShared[${JSON.stringify(key)}].loaded = true
736
- const {${JSON.stringify(key)}: pkgDynamicImport} = importMap
761
+ const {${JSON.stringify(key)}: pkgDynamicImport} = importMap
737
762
  const res = await pkgDynamicImport()
738
763
  const exportModule = {...res}
739
764
  // All npm packages pre-built by vite will be converted to esm
@@ -747,7 +772,8 @@ function generateLocalSharedImportMap() {
747
772
  },
748
773
  shareConfig: {
749
774
  singleton: ${shareItem.shareConfig.singleton},
750
- requiredVersion: ${JSON.stringify(shareItem.shareConfig.requiredVersion)}
775
+ requiredVersion: ${JSON.stringify(shareItem.shareConfig.requiredVersion)},
776
+ ${shareItem.shareConfig.import === false ? 'import: false,' : ''}
751
777
  }
752
778
  }
753
779
  `;
@@ -835,7 +861,7 @@ const hostAutoInitModule = new VirtualModule('hostAutoInit', HOST_AUTO_INIT_TAG)
835
861
  function writeHostAutoInit() {
836
862
  hostAutoInitModule.writeSync(`
837
863
  const remoteEntryPromise = import("${REMOTE_ENTRY_ID}")
838
- // __tla only serves as a hack for vite-plugin-top-level-await.
864
+ // __tla only serves as a hack for vite-plugin-top-level-await.
839
865
  Promise.resolve(remoteEntryPromise)
840
866
  .then(remoteEntry => {
841
867
  return Promise.resolve(remoteEntry.__tla)
@@ -1139,7 +1165,7 @@ const Manifest = () => {
1139
1165
  }
1140
1166
  }
1141
1167
  // Second pass: Collect all CSS assets
1142
- const allCssAssets = collectCssAssets(bundle);
1168
+ const allCssAssets = mfOptions.bundleAllCSS ? collectCssAssets(bundle) : new Set();
1143
1169
  const exposesModules = Object.keys(mfOptions.exposes).map(item => mfOptions.exposes[item].import);
1144
1170
  // Process exposed modules
1145
1171
  processModuleAssets(bundle, filesMap, modulePath => {
@@ -1163,8 +1189,10 @@ const Manifest = () => {
1163
1189
  // Process shared modules
1164
1190
  const fileToShareKey = await buildFileToShareKeyMap(getUsedShares(), this.resolve.bind(this));
1165
1191
  processModuleAssets(bundle, filesMap, modulePath => fileToShareKey.get(modulePath));
1166
- // Add all CSS assets to every export
1167
- addCssAssetsToAllExports(filesMap, allCssAssets);
1192
+ // Add all CSS assets to every export if bundleAllCSS is enabled
1193
+ if (mfOptions.bundleAllCSS) {
1194
+ addCssAssetsToAllExports(filesMap, allCssAssets);
1195
+ }
1168
1196
  // Final deduplication of all assets
1169
1197
  filesMap = deduplicateAssets(filesMap);
1170
1198
  this.emitFile({
@@ -1351,21 +1379,22 @@ function pluginProxyRemoteEntry () {
1351
1379
  return id;
1352
1380
  }
1353
1381
  },
1354
- async transform(code, id) {
1355
- if (!filter(id)) return;
1356
- if (id.includes(REMOTE_ENTRY_ID)) {
1357
- return parsePromise.then(_ => generateRemoteEntry(getNormalizeModuleFederationOptions()));
1358
- }
1359
- if (id === VIRTUAL_EXPOSES) {
1360
- return generateExposes();
1361
- }
1362
- if (id.includes(getHostAutoInitPath())) {
1363
- const options = getNormalizeModuleFederationOptions();
1364
- if (_command === 'serve') {
1365
- var _viteConfig$server, _viteConfig$server2;
1366
- const host = typeof ((_viteConfig$server = viteConfig.server) == null ? void 0 : _viteConfig$server.host) === 'string' && viteConfig.server.host !== '0.0.0.0' ? viteConfig.server.host : 'localhost';
1367
- const publicPath = JSON.stringify(resolvePublicPath(options, viteConfig.base) + options.filename);
1368
- return `
1382
+ transform(code, id) {
1383
+ const transformedCode = (() => {
1384
+ if (!filter(id)) return;
1385
+ if (id.includes(REMOTE_ENTRY_ID)) {
1386
+ return parsePromise.then(_ => generateRemoteEntry(getNormalizeModuleFederationOptions()));
1387
+ }
1388
+ if (id === VIRTUAL_EXPOSES) {
1389
+ return generateExposes();
1390
+ }
1391
+ if (id.includes(getHostAutoInitPath())) {
1392
+ const options = getNormalizeModuleFederationOptions();
1393
+ if (_command === 'serve') {
1394
+ var _viteConfig$server, _viteConfig$server2;
1395
+ const host = typeof ((_viteConfig$server = viteConfig.server) == null ? void 0 : _viteConfig$server.host) === 'string' && viteConfig.server.host !== '0.0.0.0' ? viteConfig.server.host : 'localhost';
1396
+ const publicPath = JSON.stringify(resolvePublicPath(options, viteConfig.base) + options.filename);
1397
+ return `
1369
1398
  const origin = (window && ${!options.ignoreOrigin}) ? window.origin : "//${host}:${(_viteConfig$server2 = viteConfig.server) == null ? void 0 : _viteConfig$server2.port}"
1370
1399
  const remoteEntryPromise = await import(origin + ${publicPath})
1371
1400
  // __tla only serves as a hack for vite-plugin-top-level-await.
@@ -1375,9 +1404,11 @@ function pluginProxyRemoteEntry () {
1375
1404
  .then(remoteEntry.init).catch(remoteEntry.init)
1376
1405
  })
1377
1406
  `;
1407
+ }
1408
+ return code;
1378
1409
  }
1379
- return code;
1380
- }
1410
+ })();
1411
+ return mapCodeToCodeWithSourcemap(transformedCode);
1381
1412
  }
1382
1413
  };
1383
1414
  }
@@ -1457,9 +1488,9 @@ function proxySharedModule(options) {
1457
1488
  return parsePromise.then(_ => generateLocalSharedImportMap());
1458
1489
  }
1459
1490
  },
1460
- transform(code, id) {
1491
+ transform(_, id) {
1461
1492
  if (id.includes(getLocalSharedImportMapPath())) {
1462
- return parsePromise.then(_ => generateLocalSharedImportMap());
1493
+ return mapCodeToCodeWithSourcemap(parsePromise.then(_ => generateLocalSharedImportMap()));
1463
1494
  }
1464
1495
  }
1465
1496
  }, {
@@ -1561,7 +1592,8 @@ function federation(mfUserOptions) {
1561
1592
  name,
1562
1593
  remotes,
1563
1594
  shared,
1564
- filename
1595
+ filename,
1596
+ hostInitInjectLocation
1565
1597
  } = options;
1566
1598
  if (!name) throw new Error('name is required');
1567
1599
  return [{
@@ -1581,7 +1613,7 @@ function federation(mfUserOptions) {
1581
1613
  }), ...addEntry({
1582
1614
  entryName: 'hostInit',
1583
1615
  entryPath: getHostAutoInitPath(),
1584
- inject: 'html'
1616
+ inject: hostInitInjectLocation
1585
1617
  }), ...addEntry({
1586
1618
  entryName: 'virtualExposes',
1587
1619
  entryPath: VIRTUAL_EXPOSES
package/lib/index.umd.js CHANGED
@@ -1,8 +1,8 @@
1
1
  (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('defu'), require('fs'), require('pathe'), require('@rollup/pluginutils'), require('estree-walker'), require('magic-string')) :
3
- typeof define === 'function' && define.amd ? define(['exports', 'defu', 'fs', 'pathe', '@rollup/pluginutils', 'estree-walker', 'magic-string'], factory) :
4
- (global = global || self, factory(global.vite = {}, global.defu, global.fs, global.pathe, global.pluginutils, global.estreeWalker, global.magicString));
5
- })(this, (function (exports, defu, fs, path, pluginutils, estreeWalker, MagicString) {
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('defu'), require('fs'), require('pathe'), require('magic-string'), require('@rollup/pluginutils'), require('estree-walker')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', 'defu', 'fs', 'pathe', 'magic-string', '@rollup/pluginutils', 'estree-walker'], factory) :
4
+ (global = global || self, factory(global.vite = {}, global.defu, global.fs, global.pathe, global.magicString, global.pluginutils, global.estreeWalker));
5
+ })(this, (function (exports, defu, fs, path, MagicString, pluginutils, estreeWalker) {
6
6
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
7
7
 
8
8
  function _interopNamespace(e) {
@@ -29,6 +29,21 @@
29
29
  var path__default = /*#__PURE__*/_interopDefaultLegacy(path);
30
30
  var MagicString__default = /*#__PURE__*/_interopDefaultLegacy(MagicString);
31
31
 
32
+ var mapCodeToCodeWithSourcemap = function mapCodeToCodeWithSourcemap(code) {
33
+ return Promise.resolve(code).then(function (resolvedCode) {
34
+ if (resolvedCode === undefined) {
35
+ return;
36
+ }
37
+ var s = new MagicString__default["default"](resolvedCode);
38
+ return {
39
+ code: s.toString(),
40
+ map: s.generateMap({
41
+ hires: true
42
+ })
43
+ };
44
+ });
45
+ };
46
+
32
47
  function getFirstHtmlEntryFile(entryFiles) {
33
48
  return entryFiles.find(function (file) {
34
49
  return file.endsWith('.html');
@@ -148,7 +163,7 @@
148
163
  return id.endsWith(file);
149
164
  })) {
150
165
  var injection = "\n import " + JSON.stringify(entryPath) + ";\n ";
151
- return injection + code;
166
+ return mapCodeToCodeWithSourcemap(injection + code);
152
167
  }
153
168
  }
154
169
  }];
@@ -381,6 +396,7 @@
381
396
  scope: 'default',
382
397
  from: '',
383
398
  shareConfig: {
399
+ "import": undefined,
384
400
  singleton: false,
385
401
  requiredVersion: version ? "^" + version : '*'
386
402
  }
@@ -392,6 +408,7 @@
392
408
  version: shareItem.version || version,
393
409
  scope: shareItem.shareScope || 'default',
394
410
  shareConfig: {
411
+ "import": typeof shareItem === 'object' ? shareItem["import"] : undefined,
395
412
  singleton: shareItem.singleton || false,
396
413
  requiredVersion: shareItem.requiredVersion || (version ? "^" + version : '*'),
397
414
  strictVersion: !!shareItem.strictVersion
@@ -466,7 +483,9 @@
466
483
  publicPath: options.publicPath,
467
484
  shareStrategy: options.shareStrategy || 'version-first',
468
485
  ignoreOrigin: options.ignoreOrigin || false,
469
- virtualModuleDir: options.virtualModuleDir || '__mf__virtual'
486
+ virtualModuleDir: options.virtualModuleDir || '__mf__virtual',
487
+ hostInitInjectLocation: options.hostInitInjectLocation || 'html',
488
+ bundleAllCSS: options.bundleAllCSS || false
470
489
  };
471
490
  }
472
491
 
@@ -730,12 +749,13 @@
730
749
  }
731
750
  function generateLocalSharedImportMap() {
732
751
  var options = getNormalizeModuleFederationOptions();
733
- return "\n const importMap = {\n " + Array.from(getUsedShares()).sort().map(function (pkg) {
734
- return "\n " + JSON.stringify(pkg) + ": async () => {\n let pkg = await import(\"" + getPreBuildLibImportId(pkg) + "\")\n return pkg\n }\n ";
752
+ return "\n import {loadShare} from \"@module-federation/runtime\";\n const importMap = {\n " + Array.from(getUsedShares()).sort().map(function (pkg) {
753
+ var shareItem = getNormalizeShareItem(pkg);
754
+ return "\n " + JSON.stringify(pkg) + ": async () => {\n " + ((shareItem == null ? void 0 : shareItem.shareConfig["import"]) === false ? "throw new Error(`Shared module '${" + JSON.stringify(pkg) + "}' must be provided by host`);" : "let pkg = await import(\"" + getPreBuildLibImportId(pkg) + "\");\n return pkg;") + "\n }\n ";
735
755
  }).join(',') + "\n }\n const usedShared = {\n " + Array.from(getUsedShares()).sort().map(function (key) {
736
756
  var shareItem = getNormalizeShareItem(key);
737
757
  if (!shareItem) return null;
738
- return "\n " + JSON.stringify(key) + ": {\n name: " + JSON.stringify(key) + ",\n version: " + JSON.stringify(shareItem.version) + ",\n scope: [" + JSON.stringify(shareItem.scope) + "],\n loaded: false,\n from: " + JSON.stringify(options.name) + ",\n async get () {\n usedShared[" + JSON.stringify(key) + "].loaded = true\n const {" + JSON.stringify(key) + ": pkgDynamicImport} = importMap \n const res = await pkgDynamicImport()\n const exportModule = {...res}\n // All npm packages pre-built by vite will be converted to esm\n Object.defineProperty(exportModule, \"__esModule\", {\n value: true,\n enumerable: false\n })\n return function () {\n return exportModule\n }\n },\n shareConfig: {\n singleton: " + shareItem.shareConfig.singleton + ",\n requiredVersion: " + JSON.stringify(shareItem.shareConfig.requiredVersion) + "\n }\n }\n ";
758
+ return "\n " + JSON.stringify(key) + ": {\n name: " + JSON.stringify(key) + ",\n version: " + JSON.stringify(shareItem.version) + ",\n scope: [" + JSON.stringify(shareItem.scope) + "],\n loaded: false,\n from: " + JSON.stringify(options.name) + ",\n async get () {\n if (" + (shareItem.shareConfig["import"] === false) + ") {\n throw new Error(`Shared module '${" + JSON.stringify(key) + "}' must be provided by host`);\n }\n usedShared[" + JSON.stringify(key) + "].loaded = true\n const {" + JSON.stringify(key) + ": pkgDynamicImport} = importMap\n const res = await pkgDynamicImport()\n const exportModule = {...res}\n // All npm packages pre-built by vite will be converted to esm\n Object.defineProperty(exportModule, \"__esModule\", {\n value: true,\n enumerable: false\n })\n return function () {\n return exportModule\n }\n },\n shareConfig: {\n singleton: " + shareItem.shareConfig.singleton + ",\n requiredVersion: " + JSON.stringify(shareItem.shareConfig.requiredVersion) + ",\n " + (shareItem.shareConfig["import"] === false ? 'import: false,' : '') + "\n }\n }\n ";
739
759
  }).filter(function (x) {
740
760
  return x !== null;
741
761
  }).join(',') + "\n }\n const usedRemotes = [" + Object.keys(getUsedRemotesMap()).map(function (key) {
@@ -765,7 +785,7 @@
765
785
  var HOST_AUTO_INIT_TAG = '__H_A_I__';
766
786
  var hostAutoInitModule = new VirtualModule('hostAutoInit', HOST_AUTO_INIT_TAG);
767
787
  function writeHostAutoInit() {
768
- hostAutoInitModule.writeSync("\n const remoteEntryPromise = import(\"" + REMOTE_ENTRY_ID + "\")\n // __tla only serves as a hack for vite-plugin-top-level-await. \n Promise.resolve(remoteEntryPromise)\n .then(remoteEntry => {\n return Promise.resolve(remoteEntry.__tla)\n .then(remoteEntry.init).catch(remoteEntry.init)\n })\n ");
788
+ hostAutoInitModule.writeSync("\n const remoteEntryPromise = import(\"" + REMOTE_ENTRY_ID + "\")\n // __tla only serves as a hack for vite-plugin-top-level-await.\n Promise.resolve(remoteEntryPromise)\n .then(remoteEntry => {\n return Promise.resolve(remoteEntry.__tla)\n .then(remoteEntry.init).catch(remoteEntry.init)\n })\n ");
769
789
  }
770
790
  function getHostAutoInitImportId() {
771
791
  return hostAutoInitModule.getImportId();
@@ -1090,7 +1110,7 @@
1090
1110
  }
1091
1111
  }
1092
1112
  // Second pass: Collect all CSS assets
1093
- var allCssAssets = collectCssAssets(bundle);
1113
+ var allCssAssets = mfOptions.bundleAllCSS ? collectCssAssets(bundle) : new Set();
1094
1114
  var exposesModules = Object.keys(mfOptions.exposes).map(function (item) {
1095
1115
  return mfOptions.exposes[item]["import"];
1096
1116
  });
@@ -1118,8 +1138,10 @@
1118
1138
  processModuleAssets(bundle, filesMap, function (modulePath) {
1119
1139
  return fileToShareKey.get(modulePath);
1120
1140
  });
1121
- // Add all CSS assets to every export
1122
- addCssAssetsToAllExports(filesMap, allCssAssets);
1141
+ // Add all CSS assets to every export if bundleAllCSS is enabled
1142
+ if (mfOptions.bundleAllCSS) {
1143
+ addCssAssetsToAllExports(filesMap, allCssAssets);
1144
+ }
1123
1145
  // Final deduplication of all assets
1124
1146
  filesMap = deduplicateAssets(filesMap);
1125
1147
  _this.emitFile({
@@ -1318,15 +1340,15 @@
1318
1340
  }
1319
1341
  },
1320
1342
  transform: function transform(code, id) {
1321
- try {
1322
- if (!filter(id)) return Promise.resolve();
1343
+ var transformedCode = function () {
1344
+ if (!filter(id)) return;
1323
1345
  if (id.includes(REMOTE_ENTRY_ID)) {
1324
- return Promise.resolve(parsePromise.then(function (_) {
1346
+ return parsePromise.then(function (_) {
1325
1347
  return generateRemoteEntry(getNormalizeModuleFederationOptions());
1326
- }));
1348
+ });
1327
1349
  }
1328
1350
  if (id === VIRTUAL_EXPOSES) {
1329
- return Promise.resolve(generateExposes());
1351
+ return generateExposes();
1330
1352
  }
1331
1353
  if (id.includes(getHostAutoInitPath())) {
1332
1354
  var options = getNormalizeModuleFederationOptions();
@@ -1334,14 +1356,12 @@
1334
1356
  var _viteConfig$server, _viteConfig$server2;
1335
1357
  var host = typeof ((_viteConfig$server = viteConfig.server) == null ? void 0 : _viteConfig$server.host) === 'string' && viteConfig.server.host !== '0.0.0.0' ? viteConfig.server.host : 'localhost';
1336
1358
  var publicPath = JSON.stringify(resolvePublicPath(options, viteConfig.base) + options.filename);
1337
- return Promise.resolve("\n const origin = (window && " + !options.ignoreOrigin + ") ? window.origin : \"//" + host + ":" + ((_viteConfig$server2 = viteConfig.server) == null ? void 0 : _viteConfig$server2.port) + "\"\n const remoteEntryPromise = await import(origin + " + publicPath + ")\n // __tla only serves as a hack for vite-plugin-top-level-await.\n Promise.resolve(remoteEntryPromise)\n .then(remoteEntry => {\n return Promise.resolve(remoteEntry.__tla)\n .then(remoteEntry.init).catch(remoteEntry.init)\n })\n ");
1359
+ return "\n const origin = (window && " + !options.ignoreOrigin + ") ? window.origin : \"//" + host + ":" + ((_viteConfig$server2 = viteConfig.server) == null ? void 0 : _viteConfig$server2.port) + "\"\n const remoteEntryPromise = await import(origin + " + publicPath + ")\n // __tla only serves as a hack for vite-plugin-top-level-await.\n Promise.resolve(remoteEntryPromise)\n .then(remoteEntry => {\n return Promise.resolve(remoteEntry.__tla)\n .then(remoteEntry.init).catch(remoteEntry.init)\n })\n ";
1338
1360
  }
1339
- return Promise.resolve(code);
1361
+ return code;
1340
1362
  }
1341
- return Promise.resolve();
1342
- } catch (e) {
1343
- return Promise.reject(e);
1344
- }
1363
+ }();
1364
+ return mapCodeToCodeWithSourcemap(transformedCode);
1345
1365
  }
1346
1366
  };
1347
1367
  }
@@ -1420,11 +1440,11 @@
1420
1440
  });
1421
1441
  }
1422
1442
  },
1423
- transform: function transform(code, id) {
1443
+ transform: function transform(_, id) {
1424
1444
  if (id.includes(getLocalSharedImportMapPath())) {
1425
- return parsePromise.then(function (_) {
1445
+ return mapCodeToCodeWithSourcemap(parsePromise.then(function (_) {
1426
1446
  return generateLocalSharedImportMap();
1427
- });
1447
+ }));
1428
1448
  }
1429
1449
  }
1430
1450
  }, {
@@ -1531,7 +1551,8 @@
1531
1551
  var options = normalizeModuleFederationOptions(mfUserOptions);
1532
1552
  var name = options.name,
1533
1553
  shared = options.shared,
1534
- filename = options.filename;
1554
+ filename = options.filename,
1555
+ hostInitInjectLocation = options.hostInitInjectLocation;
1535
1556
  if (!name) throw new Error('name is required');
1536
1557
  return [{
1537
1558
  name: 'vite:module-federation-config',
@@ -1550,7 +1571,7 @@
1550
1571
  }), addEntry({
1551
1572
  entryName: 'hostInit',
1552
1573
  entryPath: getHostAutoInitPath(),
1553
- inject: 'html'
1574
+ inject: hostInitInjectLocation
1554
1575
  }), addEntry({
1555
1576
  entryName: 'virtualExposes',
1556
1577
  entryPath: VIRTUAL_EXPOSES
@@ -1,9 +1,10 @@
1
1
  import { Plugin } from 'vite';
2
+ import { NormalizedModuleFederationOptions } from '../utils/normalizeModuleFederationOptions';
2
3
  interface AddEntryOptions {
3
4
  entryName: string;
4
5
  entryPath: string;
5
6
  fileName?: string;
6
- inject?: 'entry' | 'html';
7
+ inject?: NormalizedModuleFederationOptions['hostInitInjectLocation'];
7
8
  }
8
9
  declare const addEntry: ({ entryName, entryPath, fileName, inject, }: AddEntryOptions) => Plugin[];
9
10
  export default addEntry;
@@ -0,0 +1,4 @@
1
+ export declare function mapCodeToCodeWithSourcemap(code?: string | Promise<string>): Promise<{
2
+ code: string;
3
+ map: import("magic-string").SourceMap;
4
+ } | undefined>;
@@ -1,4 +1,5 @@
1
1
  import { SharedConfig, ShareStrategy } from '@module-federation/runtime/types';
2
+ import type { sharePlugin } from '@module-federation/sdk';
2
3
  export type RemoteEntryType = 'var' | 'module' | 'assign' | 'assign-properties' | 'this' | 'window' | 'self' | 'global' | 'commonjs' | 'commonjs2' | 'commonjs-module' | 'commonjs-static' | 'amd' | 'amd-require' | 'umd' | 'umd2' | 'jsonp' | 'system' | string;
3
4
  interface ExposesItem {
4
5
  import: string;
@@ -19,7 +20,7 @@ export interface ShareItem {
19
20
  version: string | undefined;
20
21
  scope: string;
21
22
  from: string;
22
- shareConfig: SharedConfig;
23
+ shareConfig: SharedConfig & sharePlugin.SharedConfig;
23
24
  }
24
25
  interface ManifestOptions {
25
26
  filePath?: string;
@@ -41,6 +42,12 @@ export type ModuleFederationOptions = {
41
42
  * Defaults to Vite's base config or "auto" if base is empty
42
43
  */
43
44
  publicPath?: string;
45
+ /**
46
+ * Controls whether all CSS assets from the bundle should be added to every exposed module.
47
+ * When false (default), the plugin will not process any CSS assets.
48
+ * When true, all CSS assets are bundled into every exposed module.
49
+ */
50
+ bundleAllCSS?: boolean;
44
51
  shared?: string[] | Record<string, string | {
45
52
  name?: string;
46
53
  version?: string;
@@ -48,6 +55,7 @@ export type ModuleFederationOptions = {
48
55
  singleton?: boolean;
49
56
  requiredVersion?: string;
50
57
  strictVersion?: boolean;
58
+ import?: sharePlugin.SharedConfig['import'];
51
59
  }> | undefined;
52
60
  runtimePlugins?: string[];
53
61
  getPublicPath?: string;
@@ -58,6 +66,7 @@ export type ModuleFederationOptions = {
58
66
  shareStrategy?: ShareStrategy;
59
67
  ignoreOrigin?: boolean;
60
68
  virtualModuleDir?: string;
69
+ hostInitInjectLocation?: HostInitInjectLocationOptions;
61
70
  };
62
71
  export interface NormalizedModuleFederationOptions {
63
72
  exposes: Record<string, ExposesItem>;
@@ -78,7 +87,15 @@ export interface NormalizedModuleFederationOptions {
78
87
  publicPath?: string;
79
88
  ignoreOrigin?: boolean;
80
89
  virtualModuleDir: string;
90
+ hostInitInjectLocation: HostInitInjectLocationOptions;
91
+ /**
92
+ * Controls whether all CSS assets from the bundle should be added to every exposed module.
93
+ * When false (default), the plugin will not process any CSS assets.
94
+ * When true, all CSS assets are bundled into every exposed module.
95
+ */
96
+ bundleAllCSS: boolean;
81
97
  }
98
+ type HostInitInjectLocationOptions = 'entry' | 'html';
82
99
  interface PluginDevOptions {
83
100
  disableLiveReload?: boolean;
84
101
  disableHotTypesReload?: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@module-federation/vite",
3
- "version": "1.8.1",
3
+ "version": "1.9.0",
4
4
  "description": "Vite plugin for Module Federation",
5
5
  "type": "module",
6
6
  "source": "src/index.ts",
@@ -9,6 +9,22 @@
9
9
  "files": [
10
10
  "lib/**/*"
11
11
  ],
12
+ "scripts": {
13
+ "prepare": "husky install",
14
+ "fmt": "prettier --write src",
15
+ "fmt.check": "prettier --check src",
16
+ "format": "pretty-quick",
17
+ "dev": "microbundle watch --no-sourcemap --compress=false",
18
+ "build": "rimraf lib && microbundle --no-sourcemap --compress=false",
19
+ "dev-rv": "pnpm -filter 'examples-rust-vite*' run dev",
20
+ "preview-rv": "pnpm -filter 'examples-rust-vite*' run preview",
21
+ "dev-vv": "pnpm -filter 'examples-vite-vite*' run dev",
22
+ "dev-nv": "pnpm -filter 'examples-nuxt-vite-host' -filter 'examples-vite-vite-remote' run dev",
23
+ "preview-vv": "pnpm -filter 'examples-vite-vite*' run preview",
24
+ "multi-example": "pnpm --filter \"multi-example-*\" --parallel run start",
25
+ "test": "vitest",
26
+ "e2e": "playwright test"
27
+ },
12
28
  "repository": {
13
29
  "type": "git",
14
30
  "url": "git+https://github.com/module-federation/vite.git"
@@ -28,8 +44,10 @@
28
44
  "url": "https://github.com/module-federation/vite/issues"
29
45
  },
30
46
  "homepage": "https://github.com/module-federation/vite#readme",
47
+ "packageManager": "pnpm@9.1.3",
31
48
  "dependencies": {
32
- "@module-federation/runtime": "^0.17.1",
49
+ "@module-federation/runtime": "^0.18.3",
50
+ "@module-federation/sdk": "^0.18.3",
33
51
  "@rollup/pluginutils": "^5.1.0",
34
52
  "defu": "^6.1.4",
35
53
  "estree-walker": "^2",
@@ -49,20 +67,5 @@
49
67
  "vite": "^5.4.3",
50
68
  "vitest": "^2.1.1",
51
69
  "wait-on": "^8.0.1"
52
- },
53
- "scripts": {
54
- "fmt": "prettier --write src",
55
- "fmt.check": "prettier --check src",
56
- "format": "pretty-quick",
57
- "dev": "microbundle watch --no-sourcemap --compress=false",
58
- "build": "rimraf lib && microbundle --no-sourcemap --compress=false",
59
- "dev-rv": "pnpm -filter 'examples-rust-vite*' run dev",
60
- "preview-rv": "pnpm -filter 'examples-rust-vite*' run preview",
61
- "dev-vv": "pnpm -filter 'examples-vite-vite*' run dev",
62
- "dev-nv": "pnpm -filter 'examples-nuxt-vite-host' -filter 'examples-vite-vite-remote' run dev",
63
- "preview-vv": "pnpm -filter 'examples-vite-vite*' run preview",
64
- "multi-example": "pnpm --filter \"multi-example-*\" --parallel run start",
65
- "test": "vitest",
66
- "e2e": "playwright test"
67
70
  }
68
- }
71
+ }