@module-federation/runtime-core 2.3.3 → 2.5.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.
Files changed (68) hide show
  1. package/dist/core.cjs +10 -2
  2. package/dist/core.cjs.map +1 -1
  3. package/dist/core.d.ts +62 -6
  4. package/dist/core.js +10 -2
  5. package/dist/core.js.map +1 -1
  6. package/dist/global.cjs +1 -1
  7. package/dist/global.js +1 -1
  8. package/dist/module/index.cjs +158 -21
  9. package/dist/module/index.cjs.map +1 -1
  10. package/dist/module/index.d.ts +5 -4
  11. package/dist/module/index.js +160 -23
  12. package/dist/module/index.js.map +1 -1
  13. package/dist/plugins/snapshot/SnapshotHandler.cjs +40 -16
  14. package/dist/plugins/snapshot/SnapshotHandler.cjs.map +1 -1
  15. package/dist/plugins/snapshot/SnapshotHandler.d.ts +5 -2
  16. package/dist/plugins/snapshot/SnapshotHandler.js +42 -18
  17. package/dist/plugins/snapshot/SnapshotHandler.js.map +1 -1
  18. package/dist/plugins/snapshot/index.cjs +6 -2
  19. package/dist/plugins/snapshot/index.cjs.map +1 -1
  20. package/dist/plugins/snapshot/index.js +6 -2
  21. package/dist/plugins/snapshot/index.js.map +1 -1
  22. package/dist/remote/index.cjs +163 -25
  23. package/dist/remote/index.cjs.map +1 -1
  24. package/dist/remote/index.d.ts +30 -4
  25. package/dist/remote/index.js +164 -26
  26. package/dist/remote/index.js.map +1 -1
  27. package/dist/shared/index.cjs +210 -95
  28. package/dist/shared/index.cjs.map +1 -1
  29. package/dist/shared/index.d.ts +22 -0
  30. package/dist/shared/index.js +211 -96
  31. package/dist/shared/index.js.map +1 -1
  32. package/dist/type/index.d.ts +2 -2
  33. package/dist/type/preload.d.ts +25 -2
  34. package/dist/types.d.ts +2 -2
  35. package/dist/utils/hooks/asyncHook.cjs +4 -1
  36. package/dist/utils/hooks/asyncHook.cjs.map +1 -1
  37. package/dist/utils/hooks/asyncHook.js +4 -1
  38. package/dist/utils/hooks/asyncHook.js.map +1 -1
  39. package/dist/utils/hooks/asyncWaterfallHooks.cjs +10 -8
  40. package/dist/utils/hooks/asyncWaterfallHooks.cjs.map +1 -1
  41. package/dist/utils/hooks/asyncWaterfallHooks.d.ts +2 -2
  42. package/dist/utils/hooks/asyncWaterfallHooks.js +10 -8
  43. package/dist/utils/hooks/asyncWaterfallHooks.js.map +1 -1
  44. package/dist/utils/hooks/syncHook.cjs +2 -1
  45. package/dist/utils/hooks/syncHook.cjs.map +1 -1
  46. package/dist/utils/hooks/syncHook.js +2 -1
  47. package/dist/utils/hooks/syncHook.js.map +1 -1
  48. package/dist/utils/hooks/syncWaterfallHook.cjs +1 -0
  49. package/dist/utils/hooks/syncWaterfallHook.cjs.map +1 -1
  50. package/dist/utils/hooks/syncWaterfallHook.d.ts +1 -1
  51. package/dist/utils/hooks/syncWaterfallHook.js +1 -0
  52. package/dist/utils/hooks/syncWaterfallHook.js.map +1 -1
  53. package/dist/utils/index.js +1 -1
  54. package/dist/utils/load.cjs +42 -10
  55. package/dist/utils/load.cjs.map +1 -1
  56. package/dist/utils/load.d.ts +2 -0
  57. package/dist/utils/load.js +42 -10
  58. package/dist/utils/load.js.map +1 -1
  59. package/dist/utils/manifest.cjs +5 -0
  60. package/dist/utils/manifest.cjs.map +1 -1
  61. package/dist/utils/manifest.js +5 -1
  62. package/dist/utils/manifest.js.map +1 -1
  63. package/dist/utils/preload.cjs +126 -64
  64. package/dist/utils/preload.cjs.map +1 -1
  65. package/dist/utils/preload.d.ts +2 -2
  66. package/dist/utils/preload.js +126 -64
  67. package/dist/utils/preload.js.map +1 -1
  68. package/package.json +3 -3
@@ -1,4 +1,4 @@
1
- import { assert, error } from "../../utils/logger.js";
1
+ import { error } from "../../utils/logger.js";
2
2
  import { isRemoteInfoWithEntry } from "../../utils/tool.js";
3
3
  import { Global, addGlobalSnapshot, getGlobalSnapshot, getGlobalSnapshotInfoByModuleInfo, getInfoWithoutType, setGlobalSnapshotInfoByModuleInfo } from "../../global.js";
4
4
  import { getRemoteInfo } from "../../utils/load.js";
@@ -9,7 +9,7 @@ import { AsyncWaterfallHook } from "../../utils/hooks/asyncWaterfallHooks.js";
9
9
  import { PluginSystem } from "../../utils/hooks/pluginSystem.js";
10
10
  import "../../utils/hooks/index.js";
11
11
  import { generateSnapshotFromManifest, isBrowserEnvValue, isManifestProvider } from "@module-federation/sdk";
12
- import { RUNTIME_003, RUNTIME_007, runtimeDescMap } from "@module-federation/error-codes";
12
+ import { RUNTIME_003, RUNTIME_007, RUNTIME_013, runtimeDescMap } from "@module-federation/error-codes";
13
13
 
14
14
  //#region src/plugins/snapshot/SnapshotHandler.ts
15
15
  function getGlobalRemoteInfo(moduleInfo, origin) {
@@ -49,11 +49,12 @@ var SnapshotHandler = class {
49
49
  this.HostInstance = HostInstance;
50
50
  this.loaderHook = HostInstance.loaderHook;
51
51
  }
52
- async loadRemoteSnapshotInfo({ moduleInfo, id, expose }) {
52
+ async loadRemoteSnapshotInfo({ moduleInfo, id, initiator = "loadRemote" }) {
53
53
  const { options } = this.HostInstance;
54
54
  await this.hooks.lifecycle.beforeLoadRemoteSnapshot.emit({
55
55
  options,
56
- moduleInfo
56
+ moduleInfo,
57
+ origin: this.HostInstance
57
58
  });
58
59
  let hostSnapshot = getGlobalSnapshotInfoByModuleInfo({
59
60
  name: this.HostInstance.options.name,
@@ -85,7 +86,10 @@ var SnapshotHandler = class {
85
86
  let gSnapshot;
86
87
  if (globalRemoteSnapshot) if (isManifestProvider(globalRemoteSnapshot)) {
87
88
  const remoteEntry = isBrowserEnvValue ? globalRemoteSnapshot.remoteEntry : globalRemoteSnapshot.ssrRemoteEntry || globalRemoteSnapshot.remoteEntry || "";
88
- const moduleSnapshot = await this.getManifestJson(remoteEntry, moduleInfo, {});
89
+ const moduleSnapshot = await this.loadManifestSnapshot(remoteEntry, moduleInfo, {}, {
90
+ initiator,
91
+ id: id || moduleInfo.name
92
+ });
89
93
  const globalSnapshotRes = setGlobalSnapshotInfoByModuleInfo({
90
94
  ...moduleInfo,
91
95
  entry: remoteEntry
@@ -103,15 +107,12 @@ var SnapshotHandler = class {
103
107
  gSnapshot = globalSnapshotRes;
104
108
  }
105
109
  else if (isRemoteInfoWithEntry(moduleInfo)) {
106
- const moduleSnapshot = await this.getManifestJson(moduleInfo.entry, moduleInfo, {});
107
- const globalSnapshotRes = setGlobalSnapshotInfoByModuleInfo(moduleInfo, moduleSnapshot);
108
- const { remoteSnapshot: remoteSnapshotRes } = await this.hooks.lifecycle.loadRemoteSnapshot.emit({
109
- options: this.HostInstance.options,
110
- moduleInfo,
111
- remoteSnapshot: moduleSnapshot,
112
- from: "global"
110
+ const moduleSnapshot = await this.loadManifestSnapshot(moduleInfo.entry, moduleInfo, {}, {
111
+ initiator,
112
+ id: id || moduleInfo.name
113
113
  });
114
- mSnapshot = remoteSnapshotRes;
114
+ const globalSnapshotRes = setGlobalSnapshotInfoByModuleInfo(moduleInfo, moduleSnapshot);
115
+ mSnapshot = moduleSnapshot;
115
116
  gSnapshot = globalSnapshotRes;
116
117
  } else error(RUNTIME_007, runtimeDescMap, {
117
118
  remoteName: moduleInfo.name,
@@ -134,12 +135,17 @@ var SnapshotHandler = class {
134
135
  getGlobalRemoteInfo(moduleInfo) {
135
136
  return getGlobalRemoteInfo(moduleInfo, this.HostInstance);
136
137
  }
137
- async getManifestJson(manifestUrl, moduleInfo, extraOptions) {
138
+ async getManifestJson(manifestUrl, moduleInfo, extraOptions, resourceOptions) {
138
139
  const getManifest = async () => {
140
+ const remoteInfo = getRemoteInfo(moduleInfo);
139
141
  let manifestJson = this.manifestCache.get(manifestUrl);
140
142
  if (manifestJson) return manifestJson;
141
143
  try {
142
- let res = await this.loaderHook.lifecycle.fetch.emit(manifestUrl, {}, getRemoteInfo(moduleInfo));
144
+ let res = await this.loaderHook.lifecycle.fetch.emit(manifestUrl, {}, remoteInfo, resourceOptions ? {
145
+ ...resourceOptions,
146
+ url: manifestUrl,
147
+ resourceType: "manifest"
148
+ } : void 0);
143
149
  if (!res || !(res instanceof Response)) res = await fetch(manifestUrl, {});
144
150
  manifestJson = await res.json();
145
151
  } catch (err) {
@@ -148,6 +154,7 @@ var SnapshotHandler = class {
148
154
  error: err,
149
155
  from: "runtime",
150
156
  lifecycle: "afterResolve",
157
+ remote: remoteInfo,
151
158
  origin: this.HostInstance
152
159
  });
153
160
  if (!manifestJson) {
@@ -159,16 +166,33 @@ var SnapshotHandler = class {
159
166
  }, `${err}`, optionsToMFContext(this.HostInstance.options));
160
167
  }
161
168
  }
162
- assert(manifestJson.metaData && manifestJson.exposes && manifestJson.shared, `"${manifestUrl}" is not a valid federation manifest for remote "${moduleInfo.name}". Missing required fields: ${[
169
+ const missingRequiredFields = [
163
170
  !manifestJson.metaData && "metaData",
164
171
  !manifestJson.exposes && "exposes",
165
172
  !manifestJson.shared && "shared"
166
- ].filter(Boolean).join(", ")}.`);
173
+ ].filter(Boolean);
174
+ if (missingRequiredFields.length > 0) await this.HostInstance.remoteHandler.hooks.lifecycle.errorLoadRemote.emit({
175
+ id: manifestUrl,
176
+ error: /* @__PURE__ */ new Error(`"${manifestUrl}" is not a valid federation manifest for remote "${moduleInfo.name}". Missing required fields: ${missingRequiredFields.join(", ")}.`),
177
+ from: "runtime",
178
+ lifecycle: "afterResolve",
179
+ remote: remoteInfo,
180
+ origin: this.HostInstance
181
+ });
182
+ if (missingRequiredFields.length > 0) error(RUNTIME_013, runtimeDescMap, {
183
+ manifestUrl,
184
+ moduleName: moduleInfo.name,
185
+ hostName: this.HostInstance.options.name,
186
+ missingFields: missingRequiredFields.join(",")
187
+ }, void 0, optionsToMFContext(this.HostInstance.options));
167
188
  this.manifestCache.set(manifestUrl, manifestJson);
168
189
  return manifestJson;
169
190
  };
191
+ return getManifest();
192
+ }
193
+ async loadManifestSnapshot(manifestUrl, moduleInfo, extraOptions, resourceOptions) {
170
194
  const asyncLoadProcess = async () => {
171
- const manifestJson = await getManifest();
195
+ const manifestJson = await this.getManifestJson(manifestUrl, moduleInfo, extraOptions, resourceOptions);
172
196
  const remoteSnapshot = generateSnapshotFromManifest(manifestJson, { version: manifestUrl });
173
197
  const { remoteSnapshot: remoteSnapshotRes } = await this.hooks.lifecycle.loadRemoteSnapshot.emit({
174
198
  options: this.HostInstance.options,
@@ -1 +1 @@
1
- {"version":3,"file":"SnapshotHandler.js","names":[],"sources":["../../../src/plugins/snapshot/SnapshotHandler.ts"],"sourcesContent":["import {\n GlobalModuleInfo,\n Manifest,\n ModuleInfo,\n generateSnapshotFromManifest,\n isManifestProvider,\n isBrowserEnvValue,\n} from '@module-federation/sdk';\nimport {\n RUNTIME_003,\n RUNTIME_007,\n runtimeDescMap,\n} from '@module-federation/error-codes';\nimport { Options, Remote } from '../../type';\nimport {\n isRemoteInfoWithEntry,\n error,\n optionsToMFContext,\n getRemoteInfo,\n} from '../../utils';\nimport {\n getGlobalSnapshot,\n setGlobalSnapshotInfoByModuleInfo,\n Global,\n addGlobalSnapshot,\n getGlobalSnapshotInfoByModuleInfo,\n getInfoWithoutType,\n} from '../../global';\nimport { PluginSystem, AsyncHook, AsyncWaterfallHook } from '../../utils/hooks';\nimport { ModuleFederation } from '../../core';\nimport { assert } from '../../utils/logger';\n\nexport function getGlobalRemoteInfo(\n moduleInfo: Remote,\n origin: ModuleFederation,\n): {\n hostGlobalSnapshot: ModuleInfo | undefined;\n globalSnapshot: ReturnType<typeof getGlobalSnapshot>;\n remoteSnapshot: GlobalModuleInfo[string] | undefined;\n} {\n const hostGlobalSnapshot = getGlobalSnapshotInfoByModuleInfo({\n name: origin.name,\n version: origin.options.version,\n });\n\n // get remote detail info from global\n const globalRemoteInfo =\n hostGlobalSnapshot &&\n 'remotesInfo' in hostGlobalSnapshot &&\n hostGlobalSnapshot.remotesInfo &&\n getInfoWithoutType(hostGlobalSnapshot.remotesInfo, moduleInfo.name).value;\n\n if (globalRemoteInfo && globalRemoteInfo.matchedVersion) {\n return {\n hostGlobalSnapshot,\n globalSnapshot: getGlobalSnapshot(),\n remoteSnapshot: getGlobalSnapshotInfoByModuleInfo({\n name: moduleInfo.name,\n version: globalRemoteInfo.matchedVersion,\n }),\n };\n }\n\n return {\n hostGlobalSnapshot: undefined,\n globalSnapshot: getGlobalSnapshot(),\n remoteSnapshot: getGlobalSnapshotInfoByModuleInfo({\n name: moduleInfo.name,\n version: 'version' in moduleInfo ? moduleInfo.version : undefined,\n }),\n };\n}\n\nexport class SnapshotHandler {\n loadingHostSnapshot: Promise<GlobalModuleInfo | void> | null = null;\n HostInstance: ModuleFederation;\n manifestCache: Map<string, Manifest> = new Map();\n hooks = new PluginSystem({\n beforeLoadRemoteSnapshot: new AsyncHook<\n [\n {\n options: Options;\n moduleInfo: Remote;\n },\n ],\n void\n >('beforeLoadRemoteSnapshot'),\n loadSnapshot: new AsyncWaterfallHook<{\n options: Options;\n moduleInfo: Remote;\n hostGlobalSnapshot: GlobalModuleInfo[string] | undefined;\n globalSnapshot: ReturnType<typeof getGlobalSnapshot>;\n remoteSnapshot?: GlobalModuleInfo[string] | undefined;\n }>('loadGlobalSnapshot'),\n loadRemoteSnapshot: new AsyncWaterfallHook<{\n options: Options;\n moduleInfo: Remote;\n manifestJson?: Manifest;\n manifestUrl?: string;\n remoteSnapshot: ModuleInfo;\n from: 'global' | 'manifest';\n }>('loadRemoteSnapshot'),\n afterLoadSnapshot: new AsyncWaterfallHook<{\n id?: string;\n host: ModuleFederation;\n options: Options;\n moduleInfo: Remote;\n remoteSnapshot: ModuleInfo;\n }>('afterLoadSnapshot'),\n });\n loaderHook: ModuleFederation['loaderHook'];\n manifestLoading: Record<string, Promise<ModuleInfo>> =\n Global.__FEDERATION__.__MANIFEST_LOADING__;\n\n constructor(HostInstance: ModuleFederation) {\n this.HostInstance = HostInstance;\n this.loaderHook = HostInstance.loaderHook;\n }\n\n // eslint-disable-next-line max-lines-per-function\n async loadRemoteSnapshotInfo({\n moduleInfo,\n id,\n expose,\n }: {\n moduleInfo: Remote;\n id?: string;\n expose?: string;\n }):\n | Promise<{\n remoteSnapshot: ModuleInfo;\n globalSnapshot: GlobalModuleInfo;\n }>\n | never {\n const { options } = this.HostInstance;\n\n await this.hooks.lifecycle.beforeLoadRemoteSnapshot.emit({\n options,\n moduleInfo,\n });\n\n let hostSnapshot = getGlobalSnapshotInfoByModuleInfo({\n name: this.HostInstance.options.name,\n version: this.HostInstance.options.version,\n });\n\n if (!hostSnapshot) {\n hostSnapshot = {\n version: this.HostInstance.options.version || '',\n remoteEntry: '',\n remotesInfo: {},\n };\n addGlobalSnapshot({\n [this.HostInstance.options.name]: hostSnapshot,\n });\n }\n\n // In dynamic loadRemote scenarios, incomplete remotesInfo delivery may occur. In such cases, the remotesInfo in the host needs to be completed in the snapshot at runtime.\n // This ensures the snapshot's integrity and helps the chrome plugin correctly identify all producer modules, ensuring that proxyable producer modules will not be missing.\n if (\n hostSnapshot &&\n 'remotesInfo' in hostSnapshot &&\n !getInfoWithoutType(hostSnapshot.remotesInfo, moduleInfo.name).value\n ) {\n if ('version' in moduleInfo || 'entry' in moduleInfo) {\n hostSnapshot.remotesInfo = {\n ...hostSnapshot?.remotesInfo,\n [moduleInfo.name]: {\n matchedVersion:\n 'version' in moduleInfo ? moduleInfo.version : moduleInfo.entry,\n },\n };\n }\n }\n\n const { hostGlobalSnapshot, remoteSnapshot, globalSnapshot } =\n this.getGlobalRemoteInfo(moduleInfo);\n const {\n remoteSnapshot: globalRemoteSnapshot,\n globalSnapshot: globalSnapshotRes,\n } = await this.hooks.lifecycle.loadSnapshot.emit({\n options,\n moduleInfo,\n hostGlobalSnapshot,\n remoteSnapshot,\n globalSnapshot,\n });\n\n let mSnapshot;\n let gSnapshot;\n // global snapshot includes manifest or module info includes manifest\n if (globalRemoteSnapshot) {\n if (isManifestProvider(globalRemoteSnapshot)) {\n const remoteEntry = isBrowserEnvValue\n ? globalRemoteSnapshot.remoteEntry\n : globalRemoteSnapshot.ssrRemoteEntry ||\n globalRemoteSnapshot.remoteEntry ||\n '';\n const moduleSnapshot = await this.getManifestJson(\n remoteEntry,\n moduleInfo,\n {},\n );\n // eslint-disable-next-line @typescript-eslint/no-shadow\n const globalSnapshotRes = setGlobalSnapshotInfoByModuleInfo(\n {\n ...moduleInfo,\n // The global remote may be overridden\n // Therefore, set the snapshot key to the global address of the actual request\n entry: remoteEntry,\n },\n moduleSnapshot,\n );\n mSnapshot = moduleSnapshot;\n gSnapshot = globalSnapshotRes;\n } else {\n const { remoteSnapshot: remoteSnapshotRes } =\n await this.hooks.lifecycle.loadRemoteSnapshot.emit({\n options: this.HostInstance.options,\n moduleInfo,\n remoteSnapshot: globalRemoteSnapshot,\n from: 'global',\n });\n mSnapshot = remoteSnapshotRes;\n gSnapshot = globalSnapshotRes;\n }\n } else {\n if (isRemoteInfoWithEntry(moduleInfo)) {\n // get from manifest.json and merge remote info from remote server\n const moduleSnapshot = await this.getManifestJson(\n moduleInfo.entry,\n moduleInfo,\n {},\n );\n // eslint-disable-next-line @typescript-eslint/no-shadow\n const globalSnapshotRes = setGlobalSnapshotInfoByModuleInfo(\n moduleInfo,\n moduleSnapshot,\n );\n const { remoteSnapshot: remoteSnapshotRes } =\n await this.hooks.lifecycle.loadRemoteSnapshot.emit({\n options: this.HostInstance.options,\n moduleInfo,\n remoteSnapshot: moduleSnapshot,\n from: 'global',\n });\n\n mSnapshot = remoteSnapshotRes;\n gSnapshot = globalSnapshotRes;\n } else {\n error(\n RUNTIME_007,\n runtimeDescMap,\n {\n remoteName: moduleInfo.name,\n remoteVersion: moduleInfo.version,\n hostName: this.HostInstance.options.name,\n globalSnapshot: JSON.stringify(globalSnapshotRes),\n },\n undefined,\n optionsToMFContext(this.HostInstance.options),\n );\n }\n }\n\n await this.hooks.lifecycle.afterLoadSnapshot.emit({\n id,\n host: this.HostInstance,\n options,\n moduleInfo,\n remoteSnapshot: mSnapshot,\n });\n\n return {\n remoteSnapshot: mSnapshot,\n globalSnapshot: gSnapshot,\n };\n }\n\n getGlobalRemoteInfo(moduleInfo: Remote): {\n hostGlobalSnapshot: ModuleInfo | undefined;\n globalSnapshot: ReturnType<typeof getGlobalSnapshot>;\n remoteSnapshot: GlobalModuleInfo[string] | undefined;\n } {\n return getGlobalRemoteInfo(moduleInfo, this.HostInstance);\n }\n\n private async getManifestJson(\n manifestUrl: string,\n moduleInfo: Remote,\n extraOptions: Record<string, any>,\n ): Promise<ModuleInfo> {\n const getManifest = async (): Promise<Manifest> => {\n let manifestJson: Manifest | undefined =\n this.manifestCache.get(manifestUrl);\n if (manifestJson) {\n return manifestJson;\n }\n try {\n let res = await this.loaderHook.lifecycle.fetch.emit(\n manifestUrl,\n {},\n getRemoteInfo(moduleInfo),\n );\n if (!res || !(res instanceof Response)) {\n res = await fetch(manifestUrl, {});\n }\n manifestJson = (await res.json()) as Manifest;\n } catch (err) {\n manifestJson =\n (await this.HostInstance.remoteHandler.hooks.lifecycle.errorLoadRemote.emit(\n {\n id: manifestUrl,\n error: err,\n from: 'runtime',\n lifecycle: 'afterResolve',\n origin: this.HostInstance,\n },\n )) as Manifest | undefined;\n\n if (!manifestJson) {\n delete this.manifestLoading[manifestUrl];\n error(\n RUNTIME_003,\n runtimeDescMap,\n {\n manifestUrl,\n moduleName: moduleInfo.name,\n hostName: this.HostInstance.options.name,\n },\n `${err}`,\n optionsToMFContext(this.HostInstance.options),\n );\n }\n }\n\n assert(\n manifestJson.metaData && manifestJson.exposes && manifestJson.shared,\n `\"${manifestUrl}\" is not a valid federation manifest for remote \"${moduleInfo.name}\". Missing required fields: ${[!manifestJson.metaData && 'metaData', !manifestJson.exposes && 'exposes', !manifestJson.shared && 'shared'].filter(Boolean).join(', ')}.`,\n );\n this.manifestCache.set(manifestUrl, manifestJson);\n return manifestJson;\n };\n\n const asyncLoadProcess = async () => {\n const manifestJson = await getManifest();\n const remoteSnapshot = generateSnapshotFromManifest(manifestJson, {\n version: manifestUrl,\n });\n\n const { remoteSnapshot: remoteSnapshotRes } =\n await this.hooks.lifecycle.loadRemoteSnapshot.emit({\n options: this.HostInstance.options,\n moduleInfo,\n manifestJson,\n remoteSnapshot,\n manifestUrl,\n from: 'manifest',\n });\n return remoteSnapshotRes;\n };\n\n if (!this.manifestLoading[manifestUrl]) {\n this.manifestLoading[manifestUrl] = asyncLoadProcess().then((res) => res);\n }\n return this.manifestLoading[manifestUrl];\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"SnapshotHandler.js","names":[],"sources":["../../../src/plugins/snapshot/SnapshotHandler.ts"],"sourcesContent":["import {\n GlobalModuleInfo,\n Manifest,\n ModuleInfo,\n generateSnapshotFromManifest,\n isManifestProvider,\n isBrowserEnvValue,\n} from '@module-federation/sdk';\nimport {\n RUNTIME_003,\n RUNTIME_007,\n RUNTIME_013,\n runtimeDescMap,\n} from '@module-federation/error-codes';\nimport { Options, Remote, ResourceLoadInitiator } from '../../type';\nimport {\n isRemoteInfoWithEntry,\n error,\n optionsToMFContext,\n getRemoteInfo,\n} from '../../utils';\nimport {\n getGlobalSnapshot,\n setGlobalSnapshotInfoByModuleInfo,\n Global,\n addGlobalSnapshot,\n getGlobalSnapshotInfoByModuleInfo,\n getInfoWithoutType,\n} from '../../global';\nimport { PluginSystem, AsyncHook, AsyncWaterfallHook } from '../../utils/hooks';\nimport { ModuleFederation } from '../../core';\n\nexport function getGlobalRemoteInfo(\n moduleInfo: Remote,\n origin: ModuleFederation,\n): {\n hostGlobalSnapshot: ModuleInfo | undefined;\n globalSnapshot: ReturnType<typeof getGlobalSnapshot>;\n remoteSnapshot: GlobalModuleInfo[string] | undefined;\n} {\n const hostGlobalSnapshot = getGlobalSnapshotInfoByModuleInfo({\n name: origin.name,\n version: origin.options.version,\n });\n\n // get remote detail info from global\n const globalRemoteInfo =\n hostGlobalSnapshot &&\n 'remotesInfo' in hostGlobalSnapshot &&\n hostGlobalSnapshot.remotesInfo &&\n getInfoWithoutType(hostGlobalSnapshot.remotesInfo, moduleInfo.name).value;\n\n if (globalRemoteInfo && globalRemoteInfo.matchedVersion) {\n return {\n hostGlobalSnapshot,\n globalSnapshot: getGlobalSnapshot(),\n remoteSnapshot: getGlobalSnapshotInfoByModuleInfo({\n name: moduleInfo.name,\n version: globalRemoteInfo.matchedVersion,\n }),\n };\n }\n\n return {\n hostGlobalSnapshot: undefined,\n globalSnapshot: getGlobalSnapshot(),\n remoteSnapshot: getGlobalSnapshotInfoByModuleInfo({\n name: moduleInfo.name,\n version: 'version' in moduleInfo ? moduleInfo.version : undefined,\n }),\n };\n}\n\nexport class SnapshotHandler {\n loadingHostSnapshot: Promise<GlobalModuleInfo | void> | null = null;\n HostInstance: ModuleFederation;\n manifestCache: Map<string, Manifest> = new Map();\n hooks = new PluginSystem({\n beforeLoadRemoteSnapshot: new AsyncHook<\n [\n {\n options: Options;\n moduleInfo: Remote;\n origin: ModuleFederation;\n },\n ],\n void\n >('beforeLoadRemoteSnapshot'),\n loadSnapshot: new AsyncWaterfallHook<{\n options: Options;\n moduleInfo: Remote;\n hostGlobalSnapshot: GlobalModuleInfo[string] | undefined;\n globalSnapshot: ReturnType<typeof getGlobalSnapshot>;\n remoteSnapshot?: GlobalModuleInfo[string] | undefined;\n }>('loadGlobalSnapshot'),\n loadRemoteSnapshot: new AsyncWaterfallHook<{\n options: Options;\n moduleInfo: Remote;\n manifestJson?: Manifest;\n manifestUrl?: string;\n remoteSnapshot: ModuleInfo;\n from: 'global' | 'manifest';\n }>('loadRemoteSnapshot'),\n afterLoadSnapshot: new AsyncWaterfallHook<{\n id?: string;\n host: ModuleFederation;\n options: Options;\n moduleInfo: Remote;\n remoteSnapshot: ModuleInfo;\n }>('afterLoadSnapshot'),\n });\n loaderHook: ModuleFederation['loaderHook'];\n manifestLoading: Record<string, Promise<ModuleInfo>> =\n Global.__FEDERATION__.__MANIFEST_LOADING__;\n\n constructor(HostInstance: ModuleFederation) {\n this.HostInstance = HostInstance;\n this.loaderHook = HostInstance.loaderHook;\n }\n\n // eslint-disable-next-line max-lines-per-function\n async loadRemoteSnapshotInfo({\n moduleInfo,\n id,\n initiator = 'loadRemote',\n }: {\n moduleInfo: Remote;\n id?: string;\n initiator?: ResourceLoadInitiator;\n }):\n | Promise<{\n remoteSnapshot: ModuleInfo;\n globalSnapshot: GlobalModuleInfo;\n }>\n | never {\n const { options } = this.HostInstance;\n\n await this.hooks.lifecycle.beforeLoadRemoteSnapshot.emit({\n options,\n moduleInfo,\n origin: this.HostInstance,\n });\n\n let hostSnapshot = getGlobalSnapshotInfoByModuleInfo({\n name: this.HostInstance.options.name,\n version: this.HostInstance.options.version,\n });\n\n if (!hostSnapshot) {\n hostSnapshot = {\n version: this.HostInstance.options.version || '',\n remoteEntry: '',\n remotesInfo: {},\n };\n addGlobalSnapshot({\n [this.HostInstance.options.name]: hostSnapshot,\n });\n }\n\n // In dynamic loadRemote scenarios, incomplete remotesInfo delivery may occur. In such cases, the remotesInfo in the host needs to be completed in the snapshot at runtime.\n // This ensures the snapshot's integrity and helps the chrome plugin correctly identify all producer modules, ensuring that proxyable producer modules will not be missing.\n if (\n hostSnapshot &&\n 'remotesInfo' in hostSnapshot &&\n !getInfoWithoutType(hostSnapshot.remotesInfo, moduleInfo.name).value\n ) {\n if ('version' in moduleInfo || 'entry' in moduleInfo) {\n hostSnapshot.remotesInfo = {\n ...hostSnapshot?.remotesInfo,\n [moduleInfo.name]: {\n matchedVersion:\n 'version' in moduleInfo ? moduleInfo.version : moduleInfo.entry,\n },\n };\n }\n }\n\n const { hostGlobalSnapshot, remoteSnapshot, globalSnapshot } =\n this.getGlobalRemoteInfo(moduleInfo);\n const {\n remoteSnapshot: globalRemoteSnapshot,\n globalSnapshot: globalSnapshotRes,\n } = await this.hooks.lifecycle.loadSnapshot.emit({\n options,\n moduleInfo,\n hostGlobalSnapshot,\n remoteSnapshot,\n globalSnapshot,\n });\n\n let mSnapshot;\n let gSnapshot;\n // global snapshot includes manifest or module info includes manifest\n if (globalRemoteSnapshot) {\n if (isManifestProvider(globalRemoteSnapshot)) {\n const remoteEntry = isBrowserEnvValue\n ? globalRemoteSnapshot.remoteEntry\n : globalRemoteSnapshot.ssrRemoteEntry ||\n globalRemoteSnapshot.remoteEntry ||\n '';\n const moduleSnapshot = await this.loadManifestSnapshot(\n remoteEntry,\n moduleInfo,\n {},\n {\n initiator,\n id: id || moduleInfo.name,\n },\n );\n // eslint-disable-next-line @typescript-eslint/no-shadow\n const globalSnapshotRes = setGlobalSnapshotInfoByModuleInfo(\n {\n ...moduleInfo,\n // The global remote may be overridden\n // Therefore, set the snapshot key to the global address of the actual request\n entry: remoteEntry,\n },\n moduleSnapshot,\n );\n mSnapshot = moduleSnapshot;\n gSnapshot = globalSnapshotRes;\n } else {\n const { remoteSnapshot: remoteSnapshotRes } =\n await this.hooks.lifecycle.loadRemoteSnapshot.emit({\n options: this.HostInstance.options,\n moduleInfo,\n remoteSnapshot: globalRemoteSnapshot,\n from: 'global',\n });\n mSnapshot = remoteSnapshotRes;\n gSnapshot = globalSnapshotRes;\n }\n } else {\n if (isRemoteInfoWithEntry(moduleInfo)) {\n // get from manifest.json and merge remote info from remote server\n const moduleSnapshot = await this.loadManifestSnapshot(\n moduleInfo.entry,\n moduleInfo,\n {},\n {\n initiator,\n id: id || moduleInfo.name,\n },\n );\n // eslint-disable-next-line @typescript-eslint/no-shadow\n const globalSnapshotRes = setGlobalSnapshotInfoByModuleInfo(\n moduleInfo,\n moduleSnapshot,\n );\n mSnapshot = moduleSnapshot;\n gSnapshot = globalSnapshotRes;\n } else {\n error(\n RUNTIME_007,\n runtimeDescMap,\n {\n remoteName: moduleInfo.name,\n remoteVersion: moduleInfo.version,\n hostName: this.HostInstance.options.name,\n globalSnapshot: JSON.stringify(globalSnapshotRes),\n },\n undefined,\n optionsToMFContext(this.HostInstance.options),\n );\n }\n }\n\n await this.hooks.lifecycle.afterLoadSnapshot.emit({\n id,\n host: this.HostInstance,\n options,\n moduleInfo,\n remoteSnapshot: mSnapshot,\n });\n\n return {\n remoteSnapshot: mSnapshot,\n globalSnapshot: gSnapshot,\n };\n }\n\n getGlobalRemoteInfo(moduleInfo: Remote): {\n hostGlobalSnapshot: ModuleInfo | undefined;\n globalSnapshot: ReturnType<typeof getGlobalSnapshot>;\n remoteSnapshot: GlobalModuleInfo[string] | undefined;\n } {\n return getGlobalRemoteInfo(moduleInfo, this.HostInstance);\n }\n\n private async getManifestJson(\n manifestUrl: string,\n moduleInfo: Remote,\n extraOptions: Record<string, any>,\n resourceOptions?: {\n initiator: ResourceLoadInitiator;\n id: string;\n },\n ): Promise<Manifest> {\n const getManifest = async (): Promise<Manifest> => {\n const remoteInfo = getRemoteInfo(moduleInfo);\n let manifestJson: Manifest | undefined =\n this.manifestCache.get(manifestUrl);\n if (manifestJson) {\n return manifestJson;\n }\n try {\n let res = await this.loaderHook.lifecycle.fetch.emit(\n manifestUrl,\n {},\n remoteInfo,\n resourceOptions\n ? {\n ...resourceOptions,\n url: manifestUrl,\n resourceType: 'manifest',\n }\n : undefined,\n );\n if (!res || !(res instanceof Response)) {\n res = await fetch(manifestUrl, {});\n }\n manifestJson = (await res.json()) as Manifest;\n } catch (err) {\n manifestJson =\n (await this.HostInstance.remoteHandler.hooks.lifecycle.errorLoadRemote.emit(\n {\n id: manifestUrl,\n error: err,\n from: 'runtime',\n lifecycle: 'afterResolve',\n remote: remoteInfo,\n origin: this.HostInstance,\n },\n )) as Manifest | undefined;\n\n if (!manifestJson) {\n delete this.manifestLoading[manifestUrl];\n error(\n RUNTIME_003,\n runtimeDescMap,\n {\n manifestUrl,\n moduleName: moduleInfo.name,\n hostName: this.HostInstance.options.name,\n },\n `${err}`,\n optionsToMFContext(this.HostInstance.options),\n );\n }\n }\n\n const missingRequiredFields = [\n !manifestJson.metaData && 'metaData',\n !manifestJson.exposes && 'exposes',\n !manifestJson.shared && 'shared',\n ].filter(Boolean);\n if (missingRequiredFields.length > 0) {\n await this.HostInstance.remoteHandler.hooks.lifecycle.errorLoadRemote.emit(\n {\n id: manifestUrl,\n error: new Error(\n `\"${manifestUrl}\" is not a valid federation manifest for remote \"${moduleInfo.name}\". Missing required fields: ${missingRequiredFields.join(', ')}.`,\n ),\n from: 'runtime',\n lifecycle: 'afterResolve',\n remote: remoteInfo,\n origin: this.HostInstance,\n },\n );\n }\n\n if (missingRequiredFields.length > 0) {\n error(\n RUNTIME_013,\n runtimeDescMap,\n {\n manifestUrl,\n moduleName: moduleInfo.name,\n hostName: this.HostInstance.options.name,\n missingFields: missingRequiredFields.join(','),\n },\n undefined,\n optionsToMFContext(this.HostInstance.options),\n );\n }\n this.manifestCache.set(manifestUrl, manifestJson);\n return manifestJson;\n };\n\n return getManifest();\n }\n\n private async loadManifestSnapshot(\n manifestUrl: string,\n moduleInfo: Remote,\n extraOptions: Record<string, any>,\n resourceOptions?: {\n initiator: ResourceLoadInitiator;\n id: string;\n },\n ): Promise<ModuleInfo> {\n const asyncLoadProcess = async () => {\n const manifestJson = await this.getManifestJson(\n manifestUrl,\n moduleInfo,\n extraOptions,\n resourceOptions,\n );\n const remoteSnapshot = generateSnapshotFromManifest(manifestJson, {\n version: manifestUrl,\n });\n\n const { remoteSnapshot: remoteSnapshotRes } =\n await this.hooks.lifecycle.loadRemoteSnapshot.emit({\n options: this.HostInstance.options,\n moduleInfo,\n manifestJson,\n remoteSnapshot,\n manifestUrl,\n from: 'manifest',\n });\n return remoteSnapshotRes;\n };\n\n if (!this.manifestLoading[manifestUrl]) {\n this.manifestLoading[manifestUrl] = asyncLoadProcess().then((res) => res);\n }\n return this.manifestLoading[manifestUrl];\n }\n}\n"],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  const require_logger = require('../../utils/logger.cjs');
2
2
  const require_tool = require('../../utils/tool.cjs');
3
+ const require_manifest = require('../../utils/manifest.cjs');
3
4
  require('../../utils/index.cjs');
4
5
  const require_preload = require('../../utils/preload.cjs');
5
6
  let _module_federation_sdk = require("@module-federation/sdk");
@@ -25,7 +26,7 @@ function snapshotPlugin() {
25
26
  if (!require_tool.isRemoteInfoWithEntry(remote) || !require_tool.isPureRemoteEntry(remote)) {
26
27
  const { remoteSnapshot, globalSnapshot } = await origin.snapshotHandler.loadRemoteSnapshotInfo({
27
28
  moduleInfo: remote,
28
- id
29
+ id: require_manifest.composeRemoteRequestId(remote.name, expose)
29
30
  });
30
31
  assignRemoteInfo(remoteInfo, remoteSnapshot);
31
32
  const preloadOptions = {
@@ -46,7 +47,10 @@ function snapshotPlugin() {
46
47
  remoteSnapshot,
47
48
  globalSnapshot
48
49
  });
49
- if (assets) require_preload.preloadAssets(remoteInfo, origin, assets, false);
50
+ if (assets) require_preload.preloadAssets(remoteInfo, origin, assets, false, {
51
+ initiator: "loadRemote",
52
+ id
53
+ }).catch(() => void 0);
50
54
  return {
51
55
  ...args,
52
56
  remoteSnapshot
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["getRemoteEntryInfoFromSnapshot","RUNTIME_011","runtimeDescMap","isBrowserEnvValue","isRemoteInfoWithEntry","isPureRemoteEntry"],"sources":["../../../src/plugins/snapshot/index.ts"],"sourcesContent":["import {\n ModuleInfo,\n getResourceUrl,\n isBrowserEnvValue,\n} from '@module-federation/sdk';\nimport { ModuleFederationRuntimePlugin } from '../../type/plugin';\nimport { RUNTIME_011, runtimeDescMap } from '@module-federation/error-codes';\nimport {\n error,\n isPureRemoteEntry,\n isRemoteInfoWithEntry,\n getRemoteEntryInfoFromSnapshot,\n} from '../../utils';\nimport { PreloadOptions, RemoteInfo } from '../../type';\nimport { preloadAssets } from '../../utils/preload';\n\nexport function assignRemoteInfo(\n remoteInfo: RemoteInfo,\n remoteSnapshot: ModuleInfo,\n): void {\n const remoteEntryInfo = getRemoteEntryInfoFromSnapshot(remoteSnapshot);\n if (!remoteEntryInfo.url) {\n error(RUNTIME_011, runtimeDescMap, { remoteName: remoteInfo.name });\n }\n\n let entryUrl = getResourceUrl(remoteSnapshot, remoteEntryInfo.url);\n\n if (!isBrowserEnvValue && !entryUrl.startsWith('http')) {\n entryUrl = `https:${entryUrl}`;\n }\n\n remoteInfo.type = remoteEntryInfo.type;\n remoteInfo.entryGlobalName = remoteEntryInfo.globalName;\n remoteInfo.entry = entryUrl;\n remoteInfo.version = remoteSnapshot.version;\n remoteInfo.buildVersion = remoteSnapshot.buildVersion;\n}\n\nexport function snapshotPlugin(): ModuleFederationRuntimePlugin {\n return {\n name: 'snapshot-plugin',\n async afterResolve(args) {\n const { remote, pkgNameOrAlias, expose, origin, remoteInfo, id } = args;\n\n if (!isRemoteInfoWithEntry(remote) || !isPureRemoteEntry(remote)) {\n const { remoteSnapshot, globalSnapshot } =\n await origin.snapshotHandler.loadRemoteSnapshotInfo({\n moduleInfo: remote,\n id,\n });\n\n assignRemoteInfo(remoteInfo, remoteSnapshot);\n // preloading assets\n const preloadOptions: PreloadOptions[0] = {\n remote,\n preloadConfig: {\n nameOrAlias: pkgNameOrAlias,\n exposes: [expose],\n resourceCategory: 'sync',\n share: false,\n depsRemote: false,\n },\n };\n\n const assets =\n await origin.remoteHandler.hooks.lifecycle.generatePreloadAssets.emit(\n {\n origin,\n preloadOptions,\n remoteInfo,\n remote,\n remoteSnapshot,\n globalSnapshot,\n },\n );\n\n if (assets) {\n preloadAssets(remoteInfo, origin, assets, false);\n }\n\n return {\n ...args,\n remoteSnapshot,\n };\n }\n\n return args;\n },\n };\n}\n"],"mappings":";;;;;;;;AAgBA,SAAgB,iBACd,YACA,gBACM;CACN,MAAM,kBAAkBA,4CAA+B,eAAe;AACtE,KAAI,CAAC,gBAAgB,IACnB,sBAAMC,4CAAaC,+CAAgB,EAAE,YAAY,WAAW,MAAM,CAAC;CAGrE,IAAI,sDAA0B,gBAAgB,gBAAgB,IAAI;AAElE,KAAI,CAACC,4CAAqB,CAAC,SAAS,WAAW,OAAO,CACpD,YAAW,SAAS;AAGtB,YAAW,OAAO,gBAAgB;AAClC,YAAW,kBAAkB,gBAAgB;AAC7C,YAAW,QAAQ;AACnB,YAAW,UAAU,eAAe;AACpC,YAAW,eAAe,eAAe;;AAG3C,SAAgB,iBAAgD;AAC9D,QAAO;EACL,MAAM;EACN,MAAM,aAAa,MAAM;GACvB,MAAM,EAAE,QAAQ,gBAAgB,QAAQ,QAAQ,YAAY,OAAO;AAEnE,OAAI,CAACC,mCAAsB,OAAO,IAAI,CAACC,+BAAkB,OAAO,EAAE;IAChE,MAAM,EAAE,gBAAgB,mBACtB,MAAM,OAAO,gBAAgB,uBAAuB;KAClD,YAAY;KACZ;KACD,CAAC;AAEJ,qBAAiB,YAAY,eAAe;IAE5C,MAAM,iBAAoC;KACxC;KACA,eAAe;MACb,aAAa;MACb,SAAS,CAAC,OAAO;MACjB,kBAAkB;MAClB,OAAO;MACP,YAAY;MACb;KACF;IAED,MAAM,SACJ,MAAM,OAAO,cAAc,MAAM,UAAU,sBAAsB,KAC/D;KACE;KACA;KACA;KACA;KACA;KACA;KACD,CACF;AAEH,QAAI,OACF,+BAAc,YAAY,QAAQ,QAAQ,MAAM;AAGlD,WAAO;KACL,GAAG;KACH;KACD;;AAGH,UAAO;;EAEV"}
1
+ {"version":3,"file":"index.cjs","names":["getRemoteEntryInfoFromSnapshot","RUNTIME_011","runtimeDescMap","isBrowserEnvValue","isRemoteInfoWithEntry","isPureRemoteEntry","composeRemoteRequestId"],"sources":["../../../src/plugins/snapshot/index.ts"],"sourcesContent":["import {\n ModuleInfo,\n getResourceUrl,\n isBrowserEnvValue,\n} from '@module-federation/sdk';\nimport { ModuleFederationRuntimePlugin } from '../../type/plugin';\nimport { RUNTIME_011, runtimeDescMap } from '@module-federation/error-codes';\nimport {\n error,\n composeRemoteRequestId,\n isPureRemoteEntry,\n isRemoteInfoWithEntry,\n getRemoteEntryInfoFromSnapshot,\n} from '../../utils';\nimport { PreloadOptions, RemoteInfo } from '../../type';\nimport { preloadAssets } from '../../utils/preload';\n\nexport function assignRemoteInfo(\n remoteInfo: RemoteInfo,\n remoteSnapshot: ModuleInfo,\n): void {\n const remoteEntryInfo = getRemoteEntryInfoFromSnapshot(remoteSnapshot);\n if (!remoteEntryInfo.url) {\n error(RUNTIME_011, runtimeDescMap, { remoteName: remoteInfo.name });\n }\n\n let entryUrl = getResourceUrl(remoteSnapshot, remoteEntryInfo.url);\n\n if (!isBrowserEnvValue && !entryUrl.startsWith('http')) {\n entryUrl = `https:${entryUrl}`;\n }\n\n remoteInfo.type = remoteEntryInfo.type;\n remoteInfo.entryGlobalName = remoteEntryInfo.globalName;\n remoteInfo.entry = entryUrl;\n remoteInfo.version = remoteSnapshot.version;\n remoteInfo.buildVersion = remoteSnapshot.buildVersion;\n}\n\nexport function snapshotPlugin(): ModuleFederationRuntimePlugin {\n return {\n name: 'snapshot-plugin',\n async afterResolve(args) {\n const { remote, pkgNameOrAlias, expose, origin, remoteInfo, id } = args;\n\n if (!isRemoteInfoWithEntry(remote) || !isPureRemoteEntry(remote)) {\n const { remoteSnapshot, globalSnapshot } =\n await origin.snapshotHandler.loadRemoteSnapshotInfo({\n moduleInfo: remote,\n id: composeRemoteRequestId(remote.name, expose),\n });\n\n assignRemoteInfo(remoteInfo, remoteSnapshot);\n // preloading assets\n const preloadOptions: PreloadOptions[0] = {\n remote,\n preloadConfig: {\n nameOrAlias: pkgNameOrAlias,\n exposes: [expose],\n resourceCategory: 'sync',\n share: false,\n depsRemote: false,\n },\n };\n\n const assets =\n await origin.remoteHandler.hooks.lifecycle.generatePreloadAssets.emit(\n {\n origin,\n preloadOptions,\n remoteInfo,\n remote,\n remoteSnapshot,\n globalSnapshot,\n },\n );\n\n if (assets) {\n preloadAssets(remoteInfo, origin, assets, false, {\n initiator: 'loadRemote',\n id,\n }).catch(() => undefined);\n }\n\n return {\n ...args,\n remoteSnapshot,\n };\n }\n\n return args;\n },\n };\n}\n"],"mappings":";;;;;;;;;AAiBA,SAAgB,iBACd,YACA,gBACM;CACN,MAAM,kBAAkBA,4CAA+B,eAAe;AACtE,KAAI,CAAC,gBAAgB,IACnB,sBAAMC,4CAAaC,+CAAgB,EAAE,YAAY,WAAW,MAAM,CAAC;CAGrE,IAAI,sDAA0B,gBAAgB,gBAAgB,IAAI;AAElE,KAAI,CAACC,4CAAqB,CAAC,SAAS,WAAW,OAAO,CACpD,YAAW,SAAS;AAGtB,YAAW,OAAO,gBAAgB;AAClC,YAAW,kBAAkB,gBAAgB;AAC7C,YAAW,QAAQ;AACnB,YAAW,UAAU,eAAe;AACpC,YAAW,eAAe,eAAe;;AAG3C,SAAgB,iBAAgD;AAC9D,QAAO;EACL,MAAM;EACN,MAAM,aAAa,MAAM;GACvB,MAAM,EAAE,QAAQ,gBAAgB,QAAQ,QAAQ,YAAY,OAAO;AAEnE,OAAI,CAACC,mCAAsB,OAAO,IAAI,CAACC,+BAAkB,OAAO,EAAE;IAChE,MAAM,EAAE,gBAAgB,mBACtB,MAAM,OAAO,gBAAgB,uBAAuB;KAClD,YAAY;KACZ,IAAIC,wCAAuB,OAAO,MAAM,OAAO;KAChD,CAAC;AAEJ,qBAAiB,YAAY,eAAe;IAE5C,MAAM,iBAAoC;KACxC;KACA,eAAe;MACb,aAAa;MACb,SAAS,CAAC,OAAO;MACjB,kBAAkB;MAClB,OAAO;MACP,YAAY;MACb;KACF;IAED,MAAM,SACJ,MAAM,OAAO,cAAc,MAAM,UAAU,sBAAsB,KAC/D;KACE;KACA;KACA;KACA;KACA;KACA;KACD,CACF;AAEH,QAAI,OACF,+BAAc,YAAY,QAAQ,QAAQ,OAAO;KAC/C,WAAW;KACX;KACD,CAAC,CAAC,YAAY,OAAU;AAG3B,WAAO;KACL,GAAG;KACH;KACD;;AAGH,UAAO;;EAEV"}
@@ -1,5 +1,6 @@
1
1
  import { error } from "../../utils/logger.js";
2
2
  import { getRemoteEntryInfoFromSnapshot, isPureRemoteEntry, isRemoteInfoWithEntry } from "../../utils/tool.js";
3
+ import { composeRemoteRequestId } from "../../utils/manifest.js";
3
4
  import "../../utils/index.js";
4
5
  import { preloadAssets } from "../../utils/preload.js";
5
6
  import { getResourceUrl, isBrowserEnvValue } from "@module-federation/sdk";
@@ -25,7 +26,7 @@ function snapshotPlugin() {
25
26
  if (!isRemoteInfoWithEntry(remote) || !isPureRemoteEntry(remote)) {
26
27
  const { remoteSnapshot, globalSnapshot } = await origin.snapshotHandler.loadRemoteSnapshotInfo({
27
28
  moduleInfo: remote,
28
- id
29
+ id: composeRemoteRequestId(remote.name, expose)
29
30
  });
30
31
  assignRemoteInfo(remoteInfo, remoteSnapshot);
31
32
  const preloadOptions = {
@@ -46,7 +47,10 @@ function snapshotPlugin() {
46
47
  remoteSnapshot,
47
48
  globalSnapshot
48
49
  });
49
- if (assets) preloadAssets(remoteInfo, origin, assets, false);
50
+ if (assets) preloadAssets(remoteInfo, origin, assets, false, {
51
+ initiator: "loadRemote",
52
+ id
53
+ }).catch(() => void 0);
50
54
  return {
51
55
  ...args,
52
56
  remoteSnapshot
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/plugins/snapshot/index.ts"],"sourcesContent":["import {\n ModuleInfo,\n getResourceUrl,\n isBrowserEnvValue,\n} from '@module-federation/sdk';\nimport { ModuleFederationRuntimePlugin } from '../../type/plugin';\nimport { RUNTIME_011, runtimeDescMap } from '@module-federation/error-codes';\nimport {\n error,\n isPureRemoteEntry,\n isRemoteInfoWithEntry,\n getRemoteEntryInfoFromSnapshot,\n} from '../../utils';\nimport { PreloadOptions, RemoteInfo } from '../../type';\nimport { preloadAssets } from '../../utils/preload';\n\nexport function assignRemoteInfo(\n remoteInfo: RemoteInfo,\n remoteSnapshot: ModuleInfo,\n): void {\n const remoteEntryInfo = getRemoteEntryInfoFromSnapshot(remoteSnapshot);\n if (!remoteEntryInfo.url) {\n error(RUNTIME_011, runtimeDescMap, { remoteName: remoteInfo.name });\n }\n\n let entryUrl = getResourceUrl(remoteSnapshot, remoteEntryInfo.url);\n\n if (!isBrowserEnvValue && !entryUrl.startsWith('http')) {\n entryUrl = `https:${entryUrl}`;\n }\n\n remoteInfo.type = remoteEntryInfo.type;\n remoteInfo.entryGlobalName = remoteEntryInfo.globalName;\n remoteInfo.entry = entryUrl;\n remoteInfo.version = remoteSnapshot.version;\n remoteInfo.buildVersion = remoteSnapshot.buildVersion;\n}\n\nexport function snapshotPlugin(): ModuleFederationRuntimePlugin {\n return {\n name: 'snapshot-plugin',\n async afterResolve(args) {\n const { remote, pkgNameOrAlias, expose, origin, remoteInfo, id } = args;\n\n if (!isRemoteInfoWithEntry(remote) || !isPureRemoteEntry(remote)) {\n const { remoteSnapshot, globalSnapshot } =\n await origin.snapshotHandler.loadRemoteSnapshotInfo({\n moduleInfo: remote,\n id,\n });\n\n assignRemoteInfo(remoteInfo, remoteSnapshot);\n // preloading assets\n const preloadOptions: PreloadOptions[0] = {\n remote,\n preloadConfig: {\n nameOrAlias: pkgNameOrAlias,\n exposes: [expose],\n resourceCategory: 'sync',\n share: false,\n depsRemote: false,\n },\n };\n\n const assets =\n await origin.remoteHandler.hooks.lifecycle.generatePreloadAssets.emit(\n {\n origin,\n preloadOptions,\n remoteInfo,\n remote,\n remoteSnapshot,\n globalSnapshot,\n },\n );\n\n if (assets) {\n preloadAssets(remoteInfo, origin, assets, false);\n }\n\n return {\n ...args,\n remoteSnapshot,\n };\n }\n\n return args;\n },\n };\n}\n"],"mappings":";;;;;;;;AAgBA,SAAgB,iBACd,YACA,gBACM;CACN,MAAM,kBAAkB,+BAA+B,eAAe;AACtE,KAAI,CAAC,gBAAgB,IACnB,OAAM,aAAa,gBAAgB,EAAE,YAAY,WAAW,MAAM,CAAC;CAGrE,IAAI,WAAW,eAAe,gBAAgB,gBAAgB,IAAI;AAElE,KAAI,CAAC,qBAAqB,CAAC,SAAS,WAAW,OAAO,CACpD,YAAW,SAAS;AAGtB,YAAW,OAAO,gBAAgB;AAClC,YAAW,kBAAkB,gBAAgB;AAC7C,YAAW,QAAQ;AACnB,YAAW,UAAU,eAAe;AACpC,YAAW,eAAe,eAAe;;AAG3C,SAAgB,iBAAgD;AAC9D,QAAO;EACL,MAAM;EACN,MAAM,aAAa,MAAM;GACvB,MAAM,EAAE,QAAQ,gBAAgB,QAAQ,QAAQ,YAAY,OAAO;AAEnE,OAAI,CAAC,sBAAsB,OAAO,IAAI,CAAC,kBAAkB,OAAO,EAAE;IAChE,MAAM,EAAE,gBAAgB,mBACtB,MAAM,OAAO,gBAAgB,uBAAuB;KAClD,YAAY;KACZ;KACD,CAAC;AAEJ,qBAAiB,YAAY,eAAe;IAE5C,MAAM,iBAAoC;KACxC;KACA,eAAe;MACb,aAAa;MACb,SAAS,CAAC,OAAO;MACjB,kBAAkB;MAClB,OAAO;MACP,YAAY;MACb;KACF;IAED,MAAM,SACJ,MAAM,OAAO,cAAc,MAAM,UAAU,sBAAsB,KAC/D;KACE;KACA;KACA;KACA;KACA;KACA;KACD,CACF;AAEH,QAAI,OACF,eAAc,YAAY,QAAQ,QAAQ,MAAM;AAGlD,WAAO;KACL,GAAG;KACH;KACD;;AAGH,UAAO;;EAEV"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/plugins/snapshot/index.ts"],"sourcesContent":["import {\n ModuleInfo,\n getResourceUrl,\n isBrowserEnvValue,\n} from '@module-federation/sdk';\nimport { ModuleFederationRuntimePlugin } from '../../type/plugin';\nimport { RUNTIME_011, runtimeDescMap } from '@module-federation/error-codes';\nimport {\n error,\n composeRemoteRequestId,\n isPureRemoteEntry,\n isRemoteInfoWithEntry,\n getRemoteEntryInfoFromSnapshot,\n} from '../../utils';\nimport { PreloadOptions, RemoteInfo } from '../../type';\nimport { preloadAssets } from '../../utils/preload';\n\nexport function assignRemoteInfo(\n remoteInfo: RemoteInfo,\n remoteSnapshot: ModuleInfo,\n): void {\n const remoteEntryInfo = getRemoteEntryInfoFromSnapshot(remoteSnapshot);\n if (!remoteEntryInfo.url) {\n error(RUNTIME_011, runtimeDescMap, { remoteName: remoteInfo.name });\n }\n\n let entryUrl = getResourceUrl(remoteSnapshot, remoteEntryInfo.url);\n\n if (!isBrowserEnvValue && !entryUrl.startsWith('http')) {\n entryUrl = `https:${entryUrl}`;\n }\n\n remoteInfo.type = remoteEntryInfo.type;\n remoteInfo.entryGlobalName = remoteEntryInfo.globalName;\n remoteInfo.entry = entryUrl;\n remoteInfo.version = remoteSnapshot.version;\n remoteInfo.buildVersion = remoteSnapshot.buildVersion;\n}\n\nexport function snapshotPlugin(): ModuleFederationRuntimePlugin {\n return {\n name: 'snapshot-plugin',\n async afterResolve(args) {\n const { remote, pkgNameOrAlias, expose, origin, remoteInfo, id } = args;\n\n if (!isRemoteInfoWithEntry(remote) || !isPureRemoteEntry(remote)) {\n const { remoteSnapshot, globalSnapshot } =\n await origin.snapshotHandler.loadRemoteSnapshotInfo({\n moduleInfo: remote,\n id: composeRemoteRequestId(remote.name, expose),\n });\n\n assignRemoteInfo(remoteInfo, remoteSnapshot);\n // preloading assets\n const preloadOptions: PreloadOptions[0] = {\n remote,\n preloadConfig: {\n nameOrAlias: pkgNameOrAlias,\n exposes: [expose],\n resourceCategory: 'sync',\n share: false,\n depsRemote: false,\n },\n };\n\n const assets =\n await origin.remoteHandler.hooks.lifecycle.generatePreloadAssets.emit(\n {\n origin,\n preloadOptions,\n remoteInfo,\n remote,\n remoteSnapshot,\n globalSnapshot,\n },\n );\n\n if (assets) {\n preloadAssets(remoteInfo, origin, assets, false, {\n initiator: 'loadRemote',\n id,\n }).catch(() => undefined);\n }\n\n return {\n ...args,\n remoteSnapshot,\n };\n }\n\n return args;\n },\n };\n}\n"],"mappings":";;;;;;;;;AAiBA,SAAgB,iBACd,YACA,gBACM;CACN,MAAM,kBAAkB,+BAA+B,eAAe;AACtE,KAAI,CAAC,gBAAgB,IACnB,OAAM,aAAa,gBAAgB,EAAE,YAAY,WAAW,MAAM,CAAC;CAGrE,IAAI,WAAW,eAAe,gBAAgB,gBAAgB,IAAI;AAElE,KAAI,CAAC,qBAAqB,CAAC,SAAS,WAAW,OAAO,CACpD,YAAW,SAAS;AAGtB,YAAW,OAAO,gBAAgB;AAClC,YAAW,kBAAkB,gBAAgB;AAC7C,YAAW,QAAQ;AACnB,YAAW,UAAU,eAAe;AACpC,YAAW,eAAe,eAAe;;AAG3C,SAAgB,iBAAgD;AAC9D,QAAO;EACL,MAAM;EACN,MAAM,aAAa,MAAM;GACvB,MAAM,EAAE,QAAQ,gBAAgB,QAAQ,QAAQ,YAAY,OAAO;AAEnE,OAAI,CAAC,sBAAsB,OAAO,IAAI,CAAC,kBAAkB,OAAO,EAAE;IAChE,MAAM,EAAE,gBAAgB,mBACtB,MAAM,OAAO,gBAAgB,uBAAuB;KAClD,YAAY;KACZ,IAAI,uBAAuB,OAAO,MAAM,OAAO;KAChD,CAAC;AAEJ,qBAAiB,YAAY,eAAe;IAE5C,MAAM,iBAAoC;KACxC;KACA,eAAe;MACb,aAAa;MACb,SAAS,CAAC,OAAO;MACjB,kBAAkB;MAClB,OAAO;MACP,YAAY;MACb;KACF;IAED,MAAM,SACJ,MAAM,OAAO,cAAc,MAAM,UAAU,sBAAsB,KAC/D;KACE;KACA;KACA;KACA;KACA;KACA;KACD,CACF;AAEH,QAAI,OACF,eAAc,YAAY,QAAQ,QAAQ,OAAO;KAC/C,WAAW;KACX;KACD,CAAC,CAAC,YAAY,OAAU;AAG3B,WAAO;KACL,GAAG;KACH;KACD;;AAGH,UAAO;;EAEV"}
@@ -25,12 +25,14 @@ var RemoteHandler = class {
25
25
  beforeRegisterRemote: new require_syncWaterfallHook.SyncWaterfallHook("beforeRegisterRemote"),
26
26
  registerRemote: new require_syncWaterfallHook.SyncWaterfallHook("registerRemote"),
27
27
  beforeRequest: new require_asyncWaterfallHooks.AsyncWaterfallHook("beforeRequest"),
28
+ afterMatchRemote: new require_asyncHook.AsyncHook("afterMatchRemote"),
28
29
  onLoad: new require_asyncHook.AsyncHook("onLoad"),
30
+ afterLoadRemote: new require_asyncHook.AsyncHook("afterLoadRemote"),
29
31
  handlePreloadModule: new require_syncHook.SyncHook("handlePreloadModule"),
30
32
  errorLoadRemote: new require_asyncHook.AsyncHook("errorLoadRemote"),
31
33
  beforePreloadRemote: new require_asyncHook.AsyncHook("beforePreloadRemote"),
32
34
  generatePreloadAssets: new require_asyncHook.AsyncHook("generatePreloadAssets"),
33
- afterPreloadRemote: new require_asyncHook.AsyncHook(),
35
+ afterPreloadRemote: new require_asyncHook.AsyncHook("afterPreloadRemote"),
34
36
  loadEntry: new require_asyncHook.AsyncHook()
35
37
  });
36
38
  this.host = host;
@@ -67,10 +69,18 @@ var RemoteHandler = class {
67
69
  }
68
70
  async loadRemote(id, options) {
69
71
  const { host } = this;
72
+ const startMatchInfo = require_manifest.matchRemoteWithNameAndExpose(host.options.remotes, id);
73
+ let completeRequestId = id;
74
+ let completeExpose = startMatchInfo?.expose;
75
+ let completeRemote = startMatchInfo ? require_load.getRemoteInfo(startMatchInfo.remote) : void 0;
76
+ let afterLoadRemoteArgs;
70
77
  try {
71
78
  const { loadFactory = true } = options || { loadFactory: true };
72
79
  const { module, moduleOptions, remoteMatchInfo } = await this.getRemoteModuleAndOptions({ id });
73
80
  const { pkgNameOrAlias, remote, expose, id: idRes, remoteSnapshot } = remoteMatchInfo;
81
+ completeRequestId = idRes;
82
+ completeExpose = expose;
83
+ completeRemote = require_load.getRemoteInfo(remote);
74
84
  const moduleOrFactory = await module.get(idRes, expose, options, remoteSnapshot);
75
85
  const moduleWrapper = await this.hooks.lifecycle.onLoad.emit({
76
86
  id: idRes,
@@ -84,44 +94,155 @@ var RemoteHandler = class {
84
94
  origin: host
85
95
  });
86
96
  this.setIdToRemoteMap(id, remoteMatchInfo);
97
+ afterLoadRemoteArgs = {
98
+ id: completeRequestId,
99
+ expose: completeExpose,
100
+ remote: completeRemote,
101
+ options,
102
+ origin: host
103
+ };
87
104
  if (typeof moduleWrapper === "function") return moduleWrapper;
88
105
  return moduleOrFactory;
89
106
  } catch (error) {
90
107
  const { from = "runtime" } = options || { from: "runtime" };
91
- const failOver = await this.hooks.lifecycle.errorLoadRemote.emit({
92
- id,
108
+ let failOver;
109
+ try {
110
+ failOver = await this.hooks.lifecycle.errorLoadRemote.emit({
111
+ id,
112
+ error,
113
+ from,
114
+ lifecycle: "onLoad",
115
+ expose: completeExpose,
116
+ remote: completeRemote,
117
+ origin: host
118
+ });
119
+ } catch (hookError) {
120
+ afterLoadRemoteArgs = {
121
+ id: completeRequestId,
122
+ expose: completeExpose,
123
+ remote: completeRemote,
124
+ options,
125
+ error: hookError,
126
+ origin: host
127
+ };
128
+ throw hookError;
129
+ }
130
+ if (!failOver) {
131
+ afterLoadRemoteArgs = {
132
+ id: completeRequestId,
133
+ expose: completeExpose,
134
+ remote: completeRemote,
135
+ options,
136
+ error,
137
+ origin: host
138
+ };
139
+ throw error;
140
+ }
141
+ afterLoadRemoteArgs = {
142
+ id: completeRequestId,
143
+ expose: completeExpose,
144
+ remote: completeRemote,
145
+ options,
93
146
  error,
94
- from,
95
- lifecycle: "onLoad",
96
- origin: host
97
- });
98
- if (!failOver) throw error;
147
+ origin: host,
148
+ recovered: true
149
+ };
99
150
  return failOver;
151
+ } finally {
152
+ if (afterLoadRemoteArgs) await this.hooks.lifecycle.afterLoadRemote.emit(afterLoadRemoteArgs);
100
153
  }
101
154
  }
102
155
  async preloadRemote(preloadOptions) {
103
156
  const { host } = this;
157
+ const preloadResults = [];
104
158
  await this.hooks.lifecycle.beforePreloadRemote.emit({
105
159
  preloadOps: preloadOptions,
106
160
  options: host.options,
107
161
  origin: host
108
162
  });
109
163
  const preloadOps = require_preload.formatPreloadArgs(host.options.remotes, preloadOptions);
110
- await Promise.all(preloadOps.map(async (ops) => {
111
- const { remote } = ops;
164
+ const createPreloadAssetOps = (ops) => {
165
+ const { preloadConfig, remote } = ops;
166
+ const exposes = preloadConfig.exposes || [];
167
+ if (!exposes.length) return [{
168
+ ops,
169
+ id: `${remote.name}/*`
170
+ }];
171
+ return exposes.map((expose) => ({
172
+ ops: {
173
+ ...ops,
174
+ preloadConfig: {
175
+ ...preloadConfig,
176
+ exposes: [expose]
177
+ }
178
+ },
179
+ id: require_manifest.composeRemoteRequestId(remote.name, expose)
180
+ }));
181
+ };
182
+ let preloadError;
183
+ await Promise.all(preloadOps.flatMap(createPreloadAssetOps).map(async (assetOps) => {
184
+ const { ops, id: preloadId } = assetOps;
185
+ const { remote, preloadConfig } = ops;
112
186
  const remoteInfo = require_load.getRemoteInfo(remote);
113
- const { globalSnapshot, remoteSnapshot } = await host.snapshotHandler.loadRemoteSnapshotInfo({ moduleInfo: remote });
114
- const assets = await this.hooks.lifecycle.generatePreloadAssets.emit({
115
- origin: host,
116
- preloadOptions: ops,
117
- remote,
118
- remoteInfo,
119
- globalSnapshot,
120
- remoteSnapshot
121
- });
122
- if (!assets) return;
123
- require_preload.preloadAssets(remoteInfo, host, assets);
187
+ try {
188
+ const { globalSnapshot, remoteSnapshot } = await host.snapshotHandler.loadRemoteSnapshotInfo({
189
+ moduleInfo: remote,
190
+ id: preloadId,
191
+ initiator: "preloadRemote"
192
+ });
193
+ const assets = await this.hooks.lifecycle.generatePreloadAssets.emit({
194
+ origin: host,
195
+ preloadOptions: ops,
196
+ remote,
197
+ remoteInfo,
198
+ globalSnapshot,
199
+ remoteSnapshot
200
+ });
201
+ if (!assets) return;
202
+ const results = await require_preload.preloadAssets(remoteInfo, host, assets, true, {
203
+ initiator: "preloadRemote",
204
+ id: preloadId
205
+ });
206
+ preloadResults.push({
207
+ remote,
208
+ remoteInfo,
209
+ preloadConfig,
210
+ id: preloadId,
211
+ results
212
+ });
213
+ } catch (error) {
214
+ preloadResults.push({
215
+ remote,
216
+ remoteInfo,
217
+ preloadConfig,
218
+ id: preloadId,
219
+ results: [{
220
+ url: remoteInfo.entry,
221
+ status: "error",
222
+ resourceType: /\.json(?:$|[?#])/i.test(remoteInfo.entry) ? "manifest" : "remoteEntry",
223
+ initiator: "preloadRemote",
224
+ id: preloadId,
225
+ error
226
+ }]
227
+ });
228
+ }
124
229
  }));
230
+ const failedResults = preloadResults.flatMap((preloadResult) => preloadResult.results.filter((result) => result.status === "error" || result.status === "timeout"));
231
+ if (failedResults.length > 0) {
232
+ preloadError = /* @__PURE__ */ new Error(`preloadRemote failed to load ${failedResults.length} resource(s).`);
233
+ Object.assign(preloadError, {
234
+ results: preloadResults,
235
+ failedResults
236
+ });
237
+ }
238
+ await this.hooks.lifecycle.afterPreloadRemote.emit({
239
+ preloadOps: preloadOptions,
240
+ options: host.options,
241
+ origin: host,
242
+ results: preloadResults,
243
+ error: preloadError
244
+ });
245
+ if (preloadError) throw preloadError;
125
246
  }
126
247
  registerRemotes(remotes, options) {
127
248
  const { host } = this;
@@ -152,12 +273,29 @@ var RemoteHandler = class {
152
273
  }
153
274
  const { id: idRes } = loadRemoteArgs;
154
275
  const remoteSplitInfo = require_manifest.matchRemoteWithNameAndExpose(host.options.remotes, idRes);
155
- if (!remoteSplitInfo) require_logger.error(_module_federation_error_codes.RUNTIME_004, _module_federation_error_codes.runtimeDescMap, {
156
- hostName: host.options.name,
157
- requestId: idRes
158
- }, void 0, require_context.optionsToMFContext(host.options));
276
+ if (!remoteSplitInfo) try {
277
+ require_logger.error(_module_federation_error_codes.RUNTIME_004, _module_federation_error_codes.runtimeDescMap, {
278
+ hostName: host.options.name,
279
+ requestId: idRes
280
+ }, void 0, require_context.optionsToMFContext(host.options));
281
+ } catch (matchError) {
282
+ await this.hooks.lifecycle.afterMatchRemote.emit({
283
+ id: idRes,
284
+ options: host.options,
285
+ error: matchError,
286
+ origin: host
287
+ });
288
+ throw matchError;
289
+ }
159
290
  const { remote: rawRemote } = remoteSplitInfo;
160
291
  const remoteInfo = require_load.getRemoteInfo(rawRemote);
292
+ await this.hooks.lifecycle.afterMatchRemote.emit({
293
+ id: idRes,
294
+ ...remoteSplitInfo,
295
+ options: host.options,
296
+ remoteInfo,
297
+ origin: host
298
+ });
161
299
  const matchInfo = await host.sharedHandler.hooks.lifecycle.afterResolve.emit({
162
300
  id: idRes,
163
301
  ...remoteSplitInfo,