@module-federation/vite 1.8.1 → 1.9.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.
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
  }];
@@ -271,12 +286,6 @@ function _unsupportedIterableToArray(r, a) {
271
286
  }
272
287
  }
273
288
 
274
- var warn = function warn(message) {
275
- return message.split('\n').forEach(function (msg) {
276
- return console.warn('\x1b[33m%s\x1b[0m', msg);
277
- });
278
- };
279
-
280
289
  function normalizeExposesItem(key, item) {
281
290
  var importPath = '';
282
291
  if (typeof item === 'string') {
@@ -383,6 +392,7 @@ function normalizeShareItem(key, shareItem) {
383
392
  scope: 'default',
384
393
  from: '',
385
394
  shareConfig: {
395
+ "import": undefined,
386
396
  singleton: false,
387
397
  requiredVersion: version ? "^" + version : '*'
388
398
  }
@@ -394,6 +404,7 @@ function normalizeShareItem(key, shareItem) {
394
404
  version: shareItem.version || version,
395
405
  scope: shareItem.shareScope || 'default',
396
406
  shareConfig: {
407
+ "import": typeof shareItem === 'object' ? shareItem["import"] : undefined,
397
408
  singleton: shareItem.singleton || false,
398
409
  requiredVersion: shareItem.requiredVersion || (version ? "^" + version : '*'),
399
410
  strictVersion: !!shareItem.strictVersion
@@ -443,9 +454,6 @@ function getNormalizeShareItem(key) {
443
454
  return shareItem;
444
455
  }
445
456
  function normalizeModuleFederationOptions(options) {
446
- if (options.getPublicPath) {
447
- warn("We are ignoring the getPublicPath options because they are natively supported by Vite\nwith the \"experimental.renderBuiltUrl\" configuration https://vitejs.dev/guide/build#advanced-base-options");
448
- }
449
457
  if (options.virtualModuleDir && options.virtualModuleDir.includes('/')) {
450
458
  throw new Error("Invalid virtualModuleDir: \"" + options.virtualModuleDir + "\". " + "The virtualModuleDir option cannot contain slashes (/). " + "Please use a single directory name like '__mf__virtual__your_app_name'.");
451
459
  }
@@ -468,7 +476,9 @@ function normalizeModuleFederationOptions(options) {
468
476
  publicPath: options.publicPath,
469
477
  shareStrategy: options.shareStrategy || 'version-first',
470
478
  ignoreOrigin: options.ignoreOrigin || false,
471
- virtualModuleDir: options.virtualModuleDir || '__mf__virtual'
479
+ virtualModuleDir: options.virtualModuleDir || '__mf__virtual',
480
+ hostInitInjectLocation: options.hostInitInjectLocation || 'html',
481
+ bundleAllCSS: options.bundleAllCSS || false
472
482
  };
473
483
  }
474
484
 
@@ -732,12 +742,13 @@ function writeLocalSharedImportMap() {
732
742
  }
733
743
  function generateLocalSharedImportMap() {
734
744
  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 ";
745
+ return "\n import {loadShare} from \"@module-federation/runtime\";\n const importMap = {\n " + Array.from(getUsedShares()).sort().map(function (pkg) {
746
+ var shareItem = getNormalizeShareItem(pkg);
747
+ 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
748
  }).join(',') + "\n }\n const usedShared = {\n " + Array.from(getUsedShares()).sort().map(function (key) {
738
749
  var shareItem = getNormalizeShareItem(key);
739
750
  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 ";
751
+ 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
752
  }).filter(function (x) {
742
753
  return x !== null;
743
754
  }).join(',') + "\n }\n const usedRemotes = [" + Object.keys(getUsedRemotesMap()).map(function (key) {
@@ -767,7 +778,7 @@ function generateRemoteEntry(options) {
767
778
  var HOST_AUTO_INIT_TAG = '__H_A_I__';
768
779
  var hostAutoInitModule = new VirtualModule('hostAutoInit', HOST_AUTO_INIT_TAG);
769
780
  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 ");
781
+ 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
782
  }
772
783
  function getHostAutoInitImportId() {
773
784
  return hostAutoInitModule.getImportId();
@@ -1092,7 +1103,7 @@ var Manifest = function Manifest() {
1092
1103
  }
1093
1104
  }
1094
1105
  // Second pass: Collect all CSS assets
1095
- var allCssAssets = collectCssAssets(bundle);
1106
+ var allCssAssets = mfOptions.bundleAllCSS ? collectCssAssets(bundle) : new Set();
1096
1107
  var exposesModules = Object.keys(mfOptions.exposes).map(function (item) {
1097
1108
  return mfOptions.exposes[item]["import"];
1098
1109
  });
@@ -1120,8 +1131,10 @@ var Manifest = function Manifest() {
1120
1131
  processModuleAssets(bundle, filesMap, function (modulePath) {
1121
1132
  return fileToShareKey.get(modulePath);
1122
1133
  });
1123
- // Add all CSS assets to every export
1124
- addCssAssetsToAllExports(filesMap, allCssAssets);
1134
+ // Add all CSS assets to every export if bundleAllCSS is enabled
1135
+ if (mfOptions.bundleAllCSS) {
1136
+ addCssAssetsToAllExports(filesMap, allCssAssets);
1137
+ }
1125
1138
  // Final deduplication of all assets
1126
1139
  filesMap = deduplicateAssets(filesMap);
1127
1140
  _this.emitFile({
@@ -1320,15 +1333,15 @@ function pluginProxyRemoteEntry () {
1320
1333
  }
1321
1334
  },
1322
1335
  transform: function transform(code, id) {
1323
- try {
1324
- if (!filter(id)) return Promise.resolve();
1336
+ var transformedCode = function () {
1337
+ if (!filter(id)) return;
1325
1338
  if (id.includes(REMOTE_ENTRY_ID)) {
1326
- return Promise.resolve(parsePromise.then(function (_) {
1339
+ return parsePromise.then(function (_) {
1327
1340
  return generateRemoteEntry(getNormalizeModuleFederationOptions());
1328
- }));
1341
+ });
1329
1342
  }
1330
1343
  if (id === VIRTUAL_EXPOSES) {
1331
- return Promise.resolve(generateExposes());
1344
+ return generateExposes();
1332
1345
  }
1333
1346
  if (id.includes(getHostAutoInitPath())) {
1334
1347
  var options = getNormalizeModuleFederationOptions();
@@ -1336,14 +1349,12 @@ function pluginProxyRemoteEntry () {
1336
1349
  var _viteConfig$server, _viteConfig$server2;
1337
1350
  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
1351
  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 ");
1352
+ 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
1353
  }
1341
- return Promise.resolve(code);
1354
+ return code;
1342
1355
  }
1343
- return Promise.resolve();
1344
- } catch (e) {
1345
- return Promise.reject(e);
1346
- }
1356
+ }();
1357
+ return mapCodeToCodeWithSourcemap(transformedCode);
1347
1358
  }
1348
1359
  };
1349
1360
  }
@@ -1422,11 +1433,11 @@ function proxySharedModule(options) {
1422
1433
  });
1423
1434
  }
1424
1435
  },
1425
- transform: function transform(code, id) {
1436
+ transform: function transform(_, id) {
1426
1437
  if (id.includes(getLocalSharedImportMapPath())) {
1427
- return parsePromise.then(function (_) {
1438
+ return mapCodeToCodeWithSourcemap(parsePromise.then(function (_) {
1428
1439
  return generateLocalSharedImportMap();
1429
- });
1440
+ }));
1430
1441
  }
1431
1442
  }
1432
1443
  }, {
@@ -1533,7 +1544,8 @@ function federation(mfUserOptions) {
1533
1544
  var options = normalizeModuleFederationOptions(mfUserOptions);
1534
1545
  var name = options.name,
1535
1546
  shared = options.shared,
1536
- filename = options.filename;
1547
+ filename = options.filename,
1548
+ hostInitInjectLocation = options.hostInitInjectLocation;
1537
1549
  if (!name) throw new Error('name is required');
1538
1550
  return [{
1539
1551
  name: 'vite:module-federation-config',
@@ -1552,7 +1564,7 @@ function federation(mfUserOptions) {
1552
1564
  }), addEntry({
1553
1565
  entryName: 'hostInit',
1554
1566
  entryPath: getHostAutoInitPath(),
1555
- inject: 'html'
1567
+ inject: hostInitInjectLocation
1556
1568
  }), addEntry({
1557
1569
  entryName: 'virtualExposes',
1558
1570
  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
  }];
@@ -247,12 +262,6 @@ function _unsupportedIterableToArray(r, a) {
247
262
  }
248
263
  }
249
264
 
250
- var warn = function warn(message) {
251
- return message.split('\n').forEach(function (msg) {
252
- return console.warn('\x1b[33m%s\x1b[0m', msg);
253
- });
254
- };
255
-
256
265
  function normalizeExposesItem(key, item) {
257
266
  var importPath = '';
258
267
  if (typeof item === 'string') {
@@ -359,6 +368,7 @@ function normalizeShareItem(key, shareItem) {
359
368
  scope: 'default',
360
369
  from: '',
361
370
  shareConfig: {
371
+ "import": undefined,
362
372
  singleton: false,
363
373
  requiredVersion: version ? "^" + version : '*'
364
374
  }
@@ -370,6 +380,7 @@ function normalizeShareItem(key, shareItem) {
370
380
  version: shareItem.version || version,
371
381
  scope: shareItem.shareScope || 'default',
372
382
  shareConfig: {
383
+ "import": typeof shareItem === 'object' ? shareItem["import"] : undefined,
373
384
  singleton: shareItem.singleton || false,
374
385
  requiredVersion: shareItem.requiredVersion || (version ? "^" + version : '*'),
375
386
  strictVersion: !!shareItem.strictVersion
@@ -419,9 +430,6 @@ function getNormalizeShareItem(key) {
419
430
  return shareItem;
420
431
  }
421
432
  function normalizeModuleFederationOptions(options) {
422
- if (options.getPublicPath) {
423
- warn("We are ignoring the getPublicPath options because they are natively supported by Vite\nwith the \"experimental.renderBuiltUrl\" configuration https://vitejs.dev/guide/build#advanced-base-options");
424
- }
425
433
  if (options.virtualModuleDir && options.virtualModuleDir.includes('/')) {
426
434
  throw new Error("Invalid virtualModuleDir: \"" + options.virtualModuleDir + "\". " + "The virtualModuleDir option cannot contain slashes (/). " + "Please use a single directory name like '__mf__virtual__your_app_name'.");
427
435
  }
@@ -444,7 +452,9 @@ function normalizeModuleFederationOptions(options) {
444
452
  publicPath: options.publicPath,
445
453
  shareStrategy: options.shareStrategy || 'version-first',
446
454
  ignoreOrigin: options.ignoreOrigin || false,
447
- virtualModuleDir: options.virtualModuleDir || '__mf__virtual'
455
+ virtualModuleDir: options.virtualModuleDir || '__mf__virtual',
456
+ hostInitInjectLocation: options.hostInitInjectLocation || 'html',
457
+ bundleAllCSS: options.bundleAllCSS || false
448
458
  };
449
459
  }
450
460
 
@@ -708,12 +718,13 @@ function writeLocalSharedImportMap() {
708
718
  }
709
719
  function generateLocalSharedImportMap() {
710
720
  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 ";
721
+ return "\n import {loadShare} from \"@module-federation/runtime\";\n const importMap = {\n " + Array.from(getUsedShares()).sort().map(function (pkg) {
722
+ var shareItem = getNormalizeShareItem(pkg);
723
+ 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
724
  }).join(',') + "\n }\n const usedShared = {\n " + Array.from(getUsedShares()).sort().map(function (key) {
714
725
  var shareItem = getNormalizeShareItem(key);
715
726
  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 ";
727
+ 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
728
  }).filter(function (x) {
718
729
  return x !== null;
719
730
  }).join(',') + "\n }\n const usedRemotes = [" + Object.keys(getUsedRemotesMap()).map(function (key) {
@@ -743,7 +754,7 @@ function generateRemoteEntry(options) {
743
754
  var HOST_AUTO_INIT_TAG = '__H_A_I__';
744
755
  var hostAutoInitModule = new VirtualModule('hostAutoInit', HOST_AUTO_INIT_TAG);
745
756
  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 ");
757
+ 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
758
  }
748
759
  function getHostAutoInitImportId() {
749
760
  return hostAutoInitModule.getImportId();
@@ -1068,7 +1079,7 @@ var Manifest = function Manifest() {
1068
1079
  }
1069
1080
  }
1070
1081
  // Second pass: Collect all CSS assets
1071
- var allCssAssets = collectCssAssets(bundle);
1082
+ var allCssAssets = mfOptions.bundleAllCSS ? collectCssAssets(bundle) : new Set();
1072
1083
  var exposesModules = Object.keys(mfOptions.exposes).map(function (item) {
1073
1084
  return mfOptions.exposes[item]["import"];
1074
1085
  });
@@ -1096,8 +1107,10 @@ var Manifest = function Manifest() {
1096
1107
  processModuleAssets(bundle, filesMap, function (modulePath) {
1097
1108
  return fileToShareKey.get(modulePath);
1098
1109
  });
1099
- // Add all CSS assets to every export
1100
- addCssAssetsToAllExports(filesMap, allCssAssets);
1110
+ // Add all CSS assets to every export if bundleAllCSS is enabled
1111
+ if (mfOptions.bundleAllCSS) {
1112
+ addCssAssetsToAllExports(filesMap, allCssAssets);
1113
+ }
1101
1114
  // Final deduplication of all assets
1102
1115
  filesMap = deduplicateAssets(filesMap);
1103
1116
  _this.emitFile({
@@ -1296,15 +1309,15 @@ function pluginProxyRemoteEntry () {
1296
1309
  }
1297
1310
  },
1298
1311
  transform: function transform(code, id) {
1299
- try {
1300
- if (!filter(id)) return Promise.resolve();
1312
+ var transformedCode = function () {
1313
+ if (!filter(id)) return;
1301
1314
  if (id.includes(REMOTE_ENTRY_ID)) {
1302
- return Promise.resolve(parsePromise.then(function (_) {
1315
+ return parsePromise.then(function (_) {
1303
1316
  return generateRemoteEntry(getNormalizeModuleFederationOptions());
1304
- }));
1317
+ });
1305
1318
  }
1306
1319
  if (id === VIRTUAL_EXPOSES) {
1307
- return Promise.resolve(generateExposes());
1320
+ return generateExposes();
1308
1321
  }
1309
1322
  if (id.includes(getHostAutoInitPath())) {
1310
1323
  var options = getNormalizeModuleFederationOptions();
@@ -1312,14 +1325,12 @@ function pluginProxyRemoteEntry () {
1312
1325
  var _viteConfig$server, _viteConfig$server2;
1313
1326
  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
1327
  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 ");
1328
+ 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
1329
  }
1317
- return Promise.resolve(code);
1330
+ return code;
1318
1331
  }
1319
- return Promise.resolve();
1320
- } catch (e) {
1321
- return Promise.reject(e);
1322
- }
1332
+ }();
1333
+ return mapCodeToCodeWithSourcemap(transformedCode);
1323
1334
  }
1324
1335
  };
1325
1336
  }
@@ -1398,11 +1409,11 @@ function proxySharedModule(options) {
1398
1409
  });
1399
1410
  }
1400
1411
  },
1401
- transform: function transform(code, id) {
1412
+ transform: function transform(_, id) {
1402
1413
  if (id.includes(getLocalSharedImportMapPath())) {
1403
- return parsePromise.then(function (_) {
1414
+ return mapCodeToCodeWithSourcemap(parsePromise.then(function (_) {
1404
1415
  return generateLocalSharedImportMap();
1405
- });
1416
+ }));
1406
1417
  }
1407
1418
  }
1408
1419
  }, {
@@ -1509,7 +1520,8 @@ function federation(mfUserOptions) {
1509
1520
  var options = normalizeModuleFederationOptions(mfUserOptions);
1510
1521
  var name = options.name,
1511
1522
  shared = options.shared,
1512
- filename = options.filename;
1523
+ filename = options.filename,
1524
+ hostInitInjectLocation = options.hostInitInjectLocation;
1513
1525
  if (!name) throw new Error('name is required');
1514
1526
  return [{
1515
1527
  name: 'vite:module-federation-config',
@@ -1528,7 +1540,7 @@ function federation(mfUserOptions) {
1528
1540
  }), addEntry({
1529
1541
  entryName: 'hostInit',
1530
1542
  entryPath: getHostAutoInitPath(),
1531
- inject: 'html'
1543
+ inject: hostInitInjectLocation
1532
1544
  }), addEntry({
1533
1545
  entryName: 'virtualExposes',
1534
1546
  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
  }];
@@ -225,8 +239,6 @@ function _extends() {
225
239
  }, _extends.apply(null, arguments);
226
240
  }
227
241
 
228
- const warn = message => message.split('\n').forEach(msg => console.warn('\x1b[33m%s\x1b[0m', msg));
229
-
230
242
  function normalizeExposesItem(key, item) {
231
243
  let importPath = '';
232
244
  if (typeof item === 'string') {
@@ -332,6 +344,7 @@ function normalizeShareItem(key, shareItem) {
332
344
  scope: 'default',
333
345
  from: '',
334
346
  shareConfig: {
347
+ import: undefined,
335
348
  singleton: false,
336
349
  requiredVersion: version ? `^${version}` : '*'
337
350
  }
@@ -343,6 +356,7 @@ function normalizeShareItem(key, shareItem) {
343
356
  version: shareItem.version || version,
344
357
  scope: shareItem.shareScope || 'default',
345
358
  shareConfig: {
359
+ import: typeof shareItem === 'object' ? shareItem.import : undefined,
346
360
  singleton: shareItem.singleton || false,
347
361
  requiredVersion: shareItem.requiredVersion || (version ? `^${version}` : '*'),
348
362
  strictVersion: !!shareItem.strictVersion
@@ -389,9 +403,6 @@ function getNormalizeShareItem(key) {
389
403
  return shareItem;
390
404
  }
391
405
  function normalizeModuleFederationOptions(options) {
392
- if (options.getPublicPath) {
393
- warn(`We are ignoring the getPublicPath options because they are natively supported by Vite\nwith the "experimental.renderBuiltUrl" configuration https://vitejs.dev/guide/build#advanced-base-options`);
394
- }
395
406
  if (options.virtualModuleDir && options.virtualModuleDir.includes('/')) {
396
407
  throw new Error(`Invalid virtualModuleDir: "${options.virtualModuleDir}". ` + `The virtualModuleDir option cannot contain slashes (/). ` + `Please use a single directory name like '__mf__virtual__your_app_name'.`);
397
408
  }
@@ -414,7 +425,9 @@ function normalizeModuleFederationOptions(options) {
414
425
  publicPath: options.publicPath,
415
426
  shareStrategy: options.shareStrategy || 'version-first',
416
427
  ignoreOrigin: options.ignoreOrigin || false,
417
- virtualModuleDir: options.virtualModuleDir || '__mf__virtual'
428
+ virtualModuleDir: options.virtualModuleDir || '__mf__virtual',
429
+ hostInitInjectLocation: options.hostInitInjectLocation || 'html',
430
+ bundleAllCSS: options.bundleAllCSS || false
418
431
  };
419
432
  }
420
433
 
@@ -712,13 +725,17 @@ function writeLocalSharedImportMap() {
712
725
  function generateLocalSharedImportMap() {
713
726
  const options = getNormalizeModuleFederationOptions();
714
727
  return `
728
+ import {loadShare} from "@module-federation/runtime";
715
729
  const importMap = {
716
- ${Array.from(getUsedShares()).sort().map(pkg => `
730
+ ${Array.from(getUsedShares()).sort().map(pkg => {
731
+ const shareItem = getNormalizeShareItem(pkg);
732
+ return `
717
733
  ${JSON.stringify(pkg)}: async () => {
718
- let pkg = await import("${getPreBuildLibImportId(pkg)}")
719
- return pkg
734
+ ${(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)}");
735
+ return pkg;`}
720
736
  }
721
- `).join(',')}
737
+ `;
738
+ }).join(',')}
722
739
  }
723
740
  const usedShared = {
724
741
  ${Array.from(getUsedShares()).sort().map(key => {
@@ -732,8 +749,11 @@ function generateLocalSharedImportMap() {
732
749
  loaded: false,
733
750
  from: ${JSON.stringify(options.name)},
734
751
  async get () {
752
+ if (${shareItem.shareConfig.import === false}) {
753
+ throw new Error(\`Shared module '\${${JSON.stringify(key)}}' must be provided by host\`);
754
+ }
735
755
  usedShared[${JSON.stringify(key)}].loaded = true
736
- const {${JSON.stringify(key)}: pkgDynamicImport} = importMap
756
+ const {${JSON.stringify(key)}: pkgDynamicImport} = importMap
737
757
  const res = await pkgDynamicImport()
738
758
  const exportModule = {...res}
739
759
  // All npm packages pre-built by vite will be converted to esm
@@ -747,7 +767,8 @@ function generateLocalSharedImportMap() {
747
767
  },
748
768
  shareConfig: {
749
769
  singleton: ${shareItem.shareConfig.singleton},
750
- requiredVersion: ${JSON.stringify(shareItem.shareConfig.requiredVersion)}
770
+ requiredVersion: ${JSON.stringify(shareItem.shareConfig.requiredVersion)},
771
+ ${shareItem.shareConfig.import === false ? 'import: false,' : ''}
751
772
  }
752
773
  }
753
774
  `;
@@ -835,7 +856,7 @@ const hostAutoInitModule = new VirtualModule('hostAutoInit', HOST_AUTO_INIT_TAG)
835
856
  function writeHostAutoInit() {
836
857
  hostAutoInitModule.writeSync(`
837
858
  const remoteEntryPromise = import("${REMOTE_ENTRY_ID}")
838
- // __tla only serves as a hack for vite-plugin-top-level-await.
859
+ // __tla only serves as a hack for vite-plugin-top-level-await.
839
860
  Promise.resolve(remoteEntryPromise)
840
861
  .then(remoteEntry => {
841
862
  return Promise.resolve(remoteEntry.__tla)
@@ -1139,7 +1160,7 @@ const Manifest = () => {
1139
1160
  }
1140
1161
  }
1141
1162
  // Second pass: Collect all CSS assets
1142
- const allCssAssets = collectCssAssets(bundle);
1163
+ const allCssAssets = mfOptions.bundleAllCSS ? collectCssAssets(bundle) : new Set();
1143
1164
  const exposesModules = Object.keys(mfOptions.exposes).map(item => mfOptions.exposes[item].import);
1144
1165
  // Process exposed modules
1145
1166
  processModuleAssets(bundle, filesMap, modulePath => {
@@ -1163,8 +1184,10 @@ const Manifest = () => {
1163
1184
  // Process shared modules
1164
1185
  const fileToShareKey = await buildFileToShareKeyMap(getUsedShares(), this.resolve.bind(this));
1165
1186
  processModuleAssets(bundle, filesMap, modulePath => fileToShareKey.get(modulePath));
1166
- // Add all CSS assets to every export
1167
- addCssAssetsToAllExports(filesMap, allCssAssets);
1187
+ // Add all CSS assets to every export if bundleAllCSS is enabled
1188
+ if (mfOptions.bundleAllCSS) {
1189
+ addCssAssetsToAllExports(filesMap, allCssAssets);
1190
+ }
1168
1191
  // Final deduplication of all assets
1169
1192
  filesMap = deduplicateAssets(filesMap);
1170
1193
  this.emitFile({
@@ -1351,21 +1374,22 @@ function pluginProxyRemoteEntry () {
1351
1374
  return id;
1352
1375
  }
1353
1376
  },
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 `
1377
+ transform(code, id) {
1378
+ const transformedCode = (() => {
1379
+ if (!filter(id)) return;
1380
+ if (id.includes(REMOTE_ENTRY_ID)) {
1381
+ return parsePromise.then(_ => generateRemoteEntry(getNormalizeModuleFederationOptions()));
1382
+ }
1383
+ if (id === VIRTUAL_EXPOSES) {
1384
+ return generateExposes();
1385
+ }
1386
+ if (id.includes(getHostAutoInitPath())) {
1387
+ const options = getNormalizeModuleFederationOptions();
1388
+ if (_command === 'serve') {
1389
+ var _viteConfig$server, _viteConfig$server2;
1390
+ 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';
1391
+ const publicPath = JSON.stringify(resolvePublicPath(options, viteConfig.base) + options.filename);
1392
+ return `
1369
1393
  const origin = (window && ${!options.ignoreOrigin}) ? window.origin : "//${host}:${(_viteConfig$server2 = viteConfig.server) == null ? void 0 : _viteConfig$server2.port}"
1370
1394
  const remoteEntryPromise = await import(origin + ${publicPath})
1371
1395
  // __tla only serves as a hack for vite-plugin-top-level-await.
@@ -1375,9 +1399,11 @@ function pluginProxyRemoteEntry () {
1375
1399
  .then(remoteEntry.init).catch(remoteEntry.init)
1376
1400
  })
1377
1401
  `;
1402
+ }
1403
+ return code;
1378
1404
  }
1379
- return code;
1380
- }
1405
+ })();
1406
+ return mapCodeToCodeWithSourcemap(transformedCode);
1381
1407
  }
1382
1408
  };
1383
1409
  }
@@ -1457,9 +1483,9 @@ function proxySharedModule(options) {
1457
1483
  return parsePromise.then(_ => generateLocalSharedImportMap());
1458
1484
  }
1459
1485
  },
1460
- transform(code, id) {
1486
+ transform(_, id) {
1461
1487
  if (id.includes(getLocalSharedImportMapPath())) {
1462
- return parsePromise.then(_ => generateLocalSharedImportMap());
1488
+ return mapCodeToCodeWithSourcemap(parsePromise.then(_ => generateLocalSharedImportMap()));
1463
1489
  }
1464
1490
  }
1465
1491
  }, {
@@ -1561,7 +1587,8 @@ function federation(mfUserOptions) {
1561
1587
  name,
1562
1588
  remotes,
1563
1589
  shared,
1564
- filename
1590
+ filename,
1591
+ hostInitInjectLocation
1565
1592
  } = options;
1566
1593
  if (!name) throw new Error('name is required');
1567
1594
  return [{
@@ -1581,7 +1608,7 @@ function federation(mfUserOptions) {
1581
1608
  }), ...addEntry({
1582
1609
  entryName: 'hostInit',
1583
1610
  entryPath: getHostAutoInitPath(),
1584
- inject: 'html'
1611
+ inject: hostInitInjectLocation
1585
1612
  }), ...addEntry({
1586
1613
  entryName: 'virtualExposes',
1587
1614
  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
  }];
@@ -269,12 +284,6 @@
269
284
  }
270
285
  }
271
286
 
272
- var warn = function warn(message) {
273
- return message.split('\n').forEach(function (msg) {
274
- return console.warn('\x1b[33m%s\x1b[0m', msg);
275
- });
276
- };
277
-
278
287
  function normalizeExposesItem(key, item) {
279
288
  var importPath = '';
280
289
  if (typeof item === 'string') {
@@ -381,6 +390,7 @@
381
390
  scope: 'default',
382
391
  from: '',
383
392
  shareConfig: {
393
+ "import": undefined,
384
394
  singleton: false,
385
395
  requiredVersion: version ? "^" + version : '*'
386
396
  }
@@ -392,6 +402,7 @@
392
402
  version: shareItem.version || version,
393
403
  scope: shareItem.shareScope || 'default',
394
404
  shareConfig: {
405
+ "import": typeof shareItem === 'object' ? shareItem["import"] : undefined,
395
406
  singleton: shareItem.singleton || false,
396
407
  requiredVersion: shareItem.requiredVersion || (version ? "^" + version : '*'),
397
408
  strictVersion: !!shareItem.strictVersion
@@ -441,9 +452,6 @@
441
452
  return shareItem;
442
453
  }
443
454
  function normalizeModuleFederationOptions(options) {
444
- if (options.getPublicPath) {
445
- warn("We are ignoring the getPublicPath options because they are natively supported by Vite\nwith the \"experimental.renderBuiltUrl\" configuration https://vitejs.dev/guide/build#advanced-base-options");
446
- }
447
455
  if (options.virtualModuleDir && options.virtualModuleDir.includes('/')) {
448
456
  throw new Error("Invalid virtualModuleDir: \"" + options.virtualModuleDir + "\". " + "The virtualModuleDir option cannot contain slashes (/). " + "Please use a single directory name like '__mf__virtual__your_app_name'.");
449
457
  }
@@ -466,7 +474,9 @@
466
474
  publicPath: options.publicPath,
467
475
  shareStrategy: options.shareStrategy || 'version-first',
468
476
  ignoreOrigin: options.ignoreOrigin || false,
469
- virtualModuleDir: options.virtualModuleDir || '__mf__virtual'
477
+ virtualModuleDir: options.virtualModuleDir || '__mf__virtual',
478
+ hostInitInjectLocation: options.hostInitInjectLocation || 'html',
479
+ bundleAllCSS: options.bundleAllCSS || false
470
480
  };
471
481
  }
472
482
 
@@ -730,12 +740,13 @@
730
740
  }
731
741
  function generateLocalSharedImportMap() {
732
742
  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 ";
743
+ return "\n import {loadShare} from \"@module-federation/runtime\";\n const importMap = {\n " + Array.from(getUsedShares()).sort().map(function (pkg) {
744
+ var shareItem = getNormalizeShareItem(pkg);
745
+ 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
746
  }).join(',') + "\n }\n const usedShared = {\n " + Array.from(getUsedShares()).sort().map(function (key) {
736
747
  var shareItem = getNormalizeShareItem(key);
737
748
  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 ";
749
+ 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
750
  }).filter(function (x) {
740
751
  return x !== null;
741
752
  }).join(',') + "\n }\n const usedRemotes = [" + Object.keys(getUsedRemotesMap()).map(function (key) {
@@ -765,7 +776,7 @@
765
776
  var HOST_AUTO_INIT_TAG = '__H_A_I__';
766
777
  var hostAutoInitModule = new VirtualModule('hostAutoInit', HOST_AUTO_INIT_TAG);
767
778
  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 ");
779
+ 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
780
  }
770
781
  function getHostAutoInitImportId() {
771
782
  return hostAutoInitModule.getImportId();
@@ -1090,7 +1101,7 @@
1090
1101
  }
1091
1102
  }
1092
1103
  // Second pass: Collect all CSS assets
1093
- var allCssAssets = collectCssAssets(bundle);
1104
+ var allCssAssets = mfOptions.bundleAllCSS ? collectCssAssets(bundle) : new Set();
1094
1105
  var exposesModules = Object.keys(mfOptions.exposes).map(function (item) {
1095
1106
  return mfOptions.exposes[item]["import"];
1096
1107
  });
@@ -1118,8 +1129,10 @@
1118
1129
  processModuleAssets(bundle, filesMap, function (modulePath) {
1119
1130
  return fileToShareKey.get(modulePath);
1120
1131
  });
1121
- // Add all CSS assets to every export
1122
- addCssAssetsToAllExports(filesMap, allCssAssets);
1132
+ // Add all CSS assets to every export if bundleAllCSS is enabled
1133
+ if (mfOptions.bundleAllCSS) {
1134
+ addCssAssetsToAllExports(filesMap, allCssAssets);
1135
+ }
1123
1136
  // Final deduplication of all assets
1124
1137
  filesMap = deduplicateAssets(filesMap);
1125
1138
  _this.emitFile({
@@ -1318,15 +1331,15 @@
1318
1331
  }
1319
1332
  },
1320
1333
  transform: function transform(code, id) {
1321
- try {
1322
- if (!filter(id)) return Promise.resolve();
1334
+ var transformedCode = function () {
1335
+ if (!filter(id)) return;
1323
1336
  if (id.includes(REMOTE_ENTRY_ID)) {
1324
- return Promise.resolve(parsePromise.then(function (_) {
1337
+ return parsePromise.then(function (_) {
1325
1338
  return generateRemoteEntry(getNormalizeModuleFederationOptions());
1326
- }));
1339
+ });
1327
1340
  }
1328
1341
  if (id === VIRTUAL_EXPOSES) {
1329
- return Promise.resolve(generateExposes());
1342
+ return generateExposes();
1330
1343
  }
1331
1344
  if (id.includes(getHostAutoInitPath())) {
1332
1345
  var options = getNormalizeModuleFederationOptions();
@@ -1334,14 +1347,12 @@
1334
1347
  var _viteConfig$server, _viteConfig$server2;
1335
1348
  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
1349
  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 ");
1350
+ 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
1351
  }
1339
- return Promise.resolve(code);
1352
+ return code;
1340
1353
  }
1341
- return Promise.resolve();
1342
- } catch (e) {
1343
- return Promise.reject(e);
1344
- }
1354
+ }();
1355
+ return mapCodeToCodeWithSourcemap(transformedCode);
1345
1356
  }
1346
1357
  };
1347
1358
  }
@@ -1420,11 +1431,11 @@
1420
1431
  });
1421
1432
  }
1422
1433
  },
1423
- transform: function transform(code, id) {
1434
+ transform: function transform(_, id) {
1424
1435
  if (id.includes(getLocalSharedImportMapPath())) {
1425
- return parsePromise.then(function (_) {
1436
+ return mapCodeToCodeWithSourcemap(parsePromise.then(function (_) {
1426
1437
  return generateLocalSharedImportMap();
1427
- });
1438
+ }));
1428
1439
  }
1429
1440
  }
1430
1441
  }, {
@@ -1531,7 +1542,8 @@
1531
1542
  var options = normalizeModuleFederationOptions(mfUserOptions);
1532
1543
  var name = options.name,
1533
1544
  shared = options.shared,
1534
- filename = options.filename;
1545
+ filename = options.filename,
1546
+ hostInitInjectLocation = options.hostInitInjectLocation;
1535
1547
  if (!name) throw new Error('name is required');
1536
1548
  return [{
1537
1549
  name: 'vite:module-federation-config',
@@ -1550,7 +1562,7 @@
1550
1562
  }), addEntry({
1551
1563
  entryName: 'hostInit',
1552
1564
  entryPath: getHostAutoInitPath(),
1553
- inject: 'html'
1565
+ inject: hostInitInjectLocation
1554
1566
  }), addEntry({
1555
1567
  entryName: 'virtualExposes',
1556
1568
  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.1",
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
+ }
@@ -1 +0,0 @@
1
- export declare const warn: (message: string) => void;