@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.
- package/dist/core.cjs +10 -2
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.ts +62 -6
- package/dist/core.js +10 -2
- package/dist/core.js.map +1 -1
- package/dist/global.cjs +1 -1
- package/dist/global.js +1 -1
- package/dist/module/index.cjs +158 -21
- package/dist/module/index.cjs.map +1 -1
- package/dist/module/index.d.ts +5 -4
- package/dist/module/index.js +160 -23
- package/dist/module/index.js.map +1 -1
- package/dist/plugins/snapshot/SnapshotHandler.cjs +40 -16
- package/dist/plugins/snapshot/SnapshotHandler.cjs.map +1 -1
- package/dist/plugins/snapshot/SnapshotHandler.d.ts +5 -2
- package/dist/plugins/snapshot/SnapshotHandler.js +42 -18
- package/dist/plugins/snapshot/SnapshotHandler.js.map +1 -1
- package/dist/plugins/snapshot/index.cjs +6 -2
- package/dist/plugins/snapshot/index.cjs.map +1 -1
- package/dist/plugins/snapshot/index.js +6 -2
- package/dist/plugins/snapshot/index.js.map +1 -1
- package/dist/remote/index.cjs +163 -25
- package/dist/remote/index.cjs.map +1 -1
- package/dist/remote/index.d.ts +30 -4
- package/dist/remote/index.js +164 -26
- package/dist/remote/index.js.map +1 -1
- package/dist/shared/index.cjs +210 -95
- package/dist/shared/index.cjs.map +1 -1
- package/dist/shared/index.d.ts +22 -0
- package/dist/shared/index.js +211 -96
- package/dist/shared/index.js.map +1 -1
- package/dist/type/index.d.ts +2 -2
- package/dist/type/preload.d.ts +25 -2
- package/dist/types.d.ts +2 -2
- package/dist/utils/hooks/asyncHook.cjs +4 -1
- package/dist/utils/hooks/asyncHook.cjs.map +1 -1
- package/dist/utils/hooks/asyncHook.js +4 -1
- package/dist/utils/hooks/asyncHook.js.map +1 -1
- package/dist/utils/hooks/asyncWaterfallHooks.cjs +10 -8
- package/dist/utils/hooks/asyncWaterfallHooks.cjs.map +1 -1
- package/dist/utils/hooks/asyncWaterfallHooks.d.ts +2 -2
- package/dist/utils/hooks/asyncWaterfallHooks.js +10 -8
- package/dist/utils/hooks/asyncWaterfallHooks.js.map +1 -1
- package/dist/utils/hooks/syncHook.cjs +2 -1
- package/dist/utils/hooks/syncHook.cjs.map +1 -1
- package/dist/utils/hooks/syncHook.js +2 -1
- package/dist/utils/hooks/syncHook.js.map +1 -1
- package/dist/utils/hooks/syncWaterfallHook.cjs +1 -0
- package/dist/utils/hooks/syncWaterfallHook.cjs.map +1 -1
- package/dist/utils/hooks/syncWaterfallHook.d.ts +1 -1
- package/dist/utils/hooks/syncWaterfallHook.js +1 -0
- package/dist/utils/hooks/syncWaterfallHook.js.map +1 -1
- package/dist/utils/index.js +1 -1
- package/dist/utils/load.cjs +42 -10
- package/dist/utils/load.cjs.map +1 -1
- package/dist/utils/load.d.ts +2 -0
- package/dist/utils/load.js +42 -10
- package/dist/utils/load.js.map +1 -1
- package/dist/utils/manifest.cjs +5 -0
- package/dist/utils/manifest.cjs.map +1 -1
- package/dist/utils/manifest.js +5 -1
- package/dist/utils/manifest.js.map +1 -1
- package/dist/utils/preload.cjs +126 -64
- package/dist/utils/preload.cjs.map +1 -1
- package/dist/utils/preload.d.ts +2 -2
- package/dist/utils/preload.js +126 -64
- package/dist/utils/preload.js.map +1 -1
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.cjs","names":[],"sources":["../../src/utils/manifest.ts"],"sourcesContent":["import { Remote } from '../type';\n\n// Function to match a remote with its name and expose\n// id: pkgName(@federation/app1) + expose(button) = @federation/app1/button\n// id: alias(app1) + expose(button) = app1/button\n// id: alias(app1/utils) + expose(loadash/sort) = app1/utils/loadash/sort\nexport function matchRemoteWithNameAndExpose(\n remotes: Array<Remote>,\n id: string,\n):\n | {\n pkgNameOrAlias: string;\n expose: string;\n remote: Remote;\n }\n | undefined {\n for (const remote of remotes) {\n // match pkgName\n const isNameMatched = id.startsWith(remote.name);\n let expose = id.replace(remote.name, '');\n if (isNameMatched) {\n if (expose.startsWith('/')) {\n const pkgNameOrAlias = remote.name;\n expose = `.${expose}`;\n return {\n pkgNameOrAlias,\n expose,\n remote,\n };\n } else if (expose === '') {\n return {\n pkgNameOrAlias: remote.name,\n expose: '.',\n remote,\n };\n }\n }\n\n // match alias\n const isAliasMatched = remote.alias && id.startsWith(remote.alias);\n let exposeWithAlias = remote.alias && id.replace(remote.alias, '');\n if (remote.alias && isAliasMatched) {\n if (exposeWithAlias && exposeWithAlias.startsWith('/')) {\n const pkgNameOrAlias = remote.alias;\n exposeWithAlias = `.${exposeWithAlias}`;\n return {\n pkgNameOrAlias,\n expose: exposeWithAlias,\n remote,\n };\n } else if (exposeWithAlias === '') {\n return {\n pkgNameOrAlias: remote.alias,\n expose: '.',\n remote,\n };\n }\n }\n }\n\n return;\n}\n\n// Function to match a remote with its name or alias\nexport function matchRemote(\n remotes: Array<Remote>,\n nameOrAlias: string,\n): Remote | undefined {\n for (const remote of remotes) {\n const isNameMatched = nameOrAlias === remote.name;\n if (isNameMatched) {\n return remote;\n }\n\n const isAliasMatched = remote.alias && nameOrAlias === remote.alias;\n if (isAliasMatched) {\n return remote;\n }\n }\n return;\n}\n"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"manifest.cjs","names":[],"sources":["../../src/utils/manifest.ts"],"sourcesContent":["import { Remote } from '../type';\n\nexport function composeRemoteRequestId(\n remoteName: string,\n expose?: string,\n): string {\n if (!expose || expose === '.') {\n return remoteName;\n }\n\n return `${remoteName}/${expose.replace(/^\\.\\//, '')}`;\n}\n\n// Function to match a remote with its name and expose\n// id: pkgName(@federation/app1) + expose(button) = @federation/app1/button\n// id: alias(app1) + expose(button) = app1/button\n// id: alias(app1/utils) + expose(loadash/sort) = app1/utils/loadash/sort\nexport function matchRemoteWithNameAndExpose(\n remotes: Array<Remote>,\n id: string,\n):\n | {\n pkgNameOrAlias: string;\n expose: string;\n remote: Remote;\n }\n | undefined {\n for (const remote of remotes) {\n // match pkgName\n const isNameMatched = id.startsWith(remote.name);\n let expose = id.replace(remote.name, '');\n if (isNameMatched) {\n if (expose.startsWith('/')) {\n const pkgNameOrAlias = remote.name;\n expose = `.${expose}`;\n return {\n pkgNameOrAlias,\n expose,\n remote,\n };\n } else if (expose === '') {\n return {\n pkgNameOrAlias: remote.name,\n expose: '.',\n remote,\n };\n }\n }\n\n // match alias\n const isAliasMatched = remote.alias && id.startsWith(remote.alias);\n let exposeWithAlias = remote.alias && id.replace(remote.alias, '');\n if (remote.alias && isAliasMatched) {\n if (exposeWithAlias && exposeWithAlias.startsWith('/')) {\n const pkgNameOrAlias = remote.alias;\n exposeWithAlias = `.${exposeWithAlias}`;\n return {\n pkgNameOrAlias,\n expose: exposeWithAlias,\n remote,\n };\n } else if (exposeWithAlias === '') {\n return {\n pkgNameOrAlias: remote.alias,\n expose: '.',\n remote,\n };\n }\n }\n }\n\n return;\n}\n\n// Function to match a remote with its name or alias\nexport function matchRemote(\n remotes: Array<Remote>,\n nameOrAlias: string,\n): Remote | undefined {\n for (const remote of remotes) {\n const isNameMatched = nameOrAlias === remote.name;\n if (isNameMatched) {\n return remote;\n }\n\n const isAliasMatched = remote.alias && nameOrAlias === remote.alias;\n if (isAliasMatched) {\n return remote;\n }\n }\n return;\n}\n"],"mappings":";;AAEA,SAAgB,uBACd,YACA,QACQ;AACR,KAAI,CAAC,UAAU,WAAW,IACxB,QAAO;AAGT,QAAO,GAAG,WAAW,GAAG,OAAO,QAAQ,SAAS,GAAG;;AAOrD,SAAgB,6BACd,SACA,IAOY;AACZ,MAAK,MAAM,UAAU,SAAS;EAE5B,MAAM,gBAAgB,GAAG,WAAW,OAAO,KAAK;EAChD,IAAI,SAAS,GAAG,QAAQ,OAAO,MAAM,GAAG;AACxC,MAAI,eACF;OAAI,OAAO,WAAW,IAAI,EAAE;IAC1B,MAAM,iBAAiB,OAAO;AAC9B,aAAS,IAAI;AACb,WAAO;KACL;KACA;KACA;KACD;cACQ,WAAW,GACpB,QAAO;IACL,gBAAgB,OAAO;IACvB,QAAQ;IACR;IACD;;EAKL,MAAM,iBAAiB,OAAO,SAAS,GAAG,WAAW,OAAO,MAAM;EAClE,IAAI,kBAAkB,OAAO,SAAS,GAAG,QAAQ,OAAO,OAAO,GAAG;AAClE,MAAI,OAAO,SAAS,gBAClB;OAAI,mBAAmB,gBAAgB,WAAW,IAAI,EAAE;IACtD,MAAM,iBAAiB,OAAO;AAC9B,sBAAkB,IAAI;AACtB,WAAO;KACL;KACA,QAAQ;KACR;KACD;cACQ,oBAAoB,GAC7B,QAAO;IACL,gBAAgB,OAAO;IACvB,QAAQ;IACR;IACD;;;;AAST,SAAgB,YACd,SACA,aACoB;AACpB,MAAK,MAAM,UAAU,SAAS;AAE5B,MADsB,gBAAgB,OAAO,KAE3C,QAAO;AAIT,MADuB,OAAO,SAAS,gBAAgB,OAAO,MAE5D,QAAO"}
|
package/dist/utils/manifest.js
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
//#region src/utils/manifest.ts
|
|
2
|
+
function composeRemoteRequestId(remoteName, expose) {
|
|
3
|
+
if (!expose || expose === ".") return remoteName;
|
|
4
|
+
return `${remoteName}/${expose.replace(/^\.\//, "")}`;
|
|
5
|
+
}
|
|
2
6
|
function matchRemoteWithNameAndExpose(remotes, id) {
|
|
3
7
|
for (const remote of remotes) {
|
|
4
8
|
const isNameMatched = id.startsWith(remote.name);
|
|
@@ -45,5 +49,5 @@ function matchRemote(remotes, nameOrAlias) {
|
|
|
45
49
|
}
|
|
46
50
|
|
|
47
51
|
//#endregion
|
|
48
|
-
export { matchRemote, matchRemoteWithNameAndExpose };
|
|
52
|
+
export { composeRemoteRequestId, matchRemote, matchRemoteWithNameAndExpose };
|
|
49
53
|
//# sourceMappingURL=manifest.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.js","names":[],"sources":["../../src/utils/manifest.ts"],"sourcesContent":["import { Remote } from '../type';\n\n// Function to match a remote with its name and expose\n// id: pkgName(@federation/app1) + expose(button) = @federation/app1/button\n// id: alias(app1) + expose(button) = app1/button\n// id: alias(app1/utils) + expose(loadash/sort) = app1/utils/loadash/sort\nexport function matchRemoteWithNameAndExpose(\n remotes: Array<Remote>,\n id: string,\n):\n | {\n pkgNameOrAlias: string;\n expose: string;\n remote: Remote;\n }\n | undefined {\n for (const remote of remotes) {\n // match pkgName\n const isNameMatched = id.startsWith(remote.name);\n let expose = id.replace(remote.name, '');\n if (isNameMatched) {\n if (expose.startsWith('/')) {\n const pkgNameOrAlias = remote.name;\n expose = `.${expose}`;\n return {\n pkgNameOrAlias,\n expose,\n remote,\n };\n } else if (expose === '') {\n return {\n pkgNameOrAlias: remote.name,\n expose: '.',\n remote,\n };\n }\n }\n\n // match alias\n const isAliasMatched = remote.alias && id.startsWith(remote.alias);\n let exposeWithAlias = remote.alias && id.replace(remote.alias, '');\n if (remote.alias && isAliasMatched) {\n if (exposeWithAlias && exposeWithAlias.startsWith('/')) {\n const pkgNameOrAlias = remote.alias;\n exposeWithAlias = `.${exposeWithAlias}`;\n return {\n pkgNameOrAlias,\n expose: exposeWithAlias,\n remote,\n };\n } else if (exposeWithAlias === '') {\n return {\n pkgNameOrAlias: remote.alias,\n expose: '.',\n remote,\n };\n }\n }\n }\n\n return;\n}\n\n// Function to match a remote with its name or alias\nexport function matchRemote(\n remotes: Array<Remote>,\n nameOrAlias: string,\n): Remote | undefined {\n for (const remote of remotes) {\n const isNameMatched = nameOrAlias === remote.name;\n if (isNameMatched) {\n return remote;\n }\n\n const isAliasMatched = remote.alias && nameOrAlias === remote.alias;\n if (isAliasMatched) {\n return remote;\n }\n }\n return;\n}\n"],"mappings":";
|
|
1
|
+
{"version":3,"file":"manifest.js","names":[],"sources":["../../src/utils/manifest.ts"],"sourcesContent":["import { Remote } from '../type';\n\nexport function composeRemoteRequestId(\n remoteName: string,\n expose?: string,\n): string {\n if (!expose || expose === '.') {\n return remoteName;\n }\n\n return `${remoteName}/${expose.replace(/^\\.\\//, '')}`;\n}\n\n// Function to match a remote with its name and expose\n// id: pkgName(@federation/app1) + expose(button) = @federation/app1/button\n// id: alias(app1) + expose(button) = app1/button\n// id: alias(app1/utils) + expose(loadash/sort) = app1/utils/loadash/sort\nexport function matchRemoteWithNameAndExpose(\n remotes: Array<Remote>,\n id: string,\n):\n | {\n pkgNameOrAlias: string;\n expose: string;\n remote: Remote;\n }\n | undefined {\n for (const remote of remotes) {\n // match pkgName\n const isNameMatched = id.startsWith(remote.name);\n let expose = id.replace(remote.name, '');\n if (isNameMatched) {\n if (expose.startsWith('/')) {\n const pkgNameOrAlias = remote.name;\n expose = `.${expose}`;\n return {\n pkgNameOrAlias,\n expose,\n remote,\n };\n } else if (expose === '') {\n return {\n pkgNameOrAlias: remote.name,\n expose: '.',\n remote,\n };\n }\n }\n\n // match alias\n const isAliasMatched = remote.alias && id.startsWith(remote.alias);\n let exposeWithAlias = remote.alias && id.replace(remote.alias, '');\n if (remote.alias && isAliasMatched) {\n if (exposeWithAlias && exposeWithAlias.startsWith('/')) {\n const pkgNameOrAlias = remote.alias;\n exposeWithAlias = `.${exposeWithAlias}`;\n return {\n pkgNameOrAlias,\n expose: exposeWithAlias,\n remote,\n };\n } else if (exposeWithAlias === '') {\n return {\n pkgNameOrAlias: remote.alias,\n expose: '.',\n remote,\n };\n }\n }\n }\n\n return;\n}\n\n// Function to match a remote with its name or alias\nexport function matchRemote(\n remotes: Array<Remote>,\n nameOrAlias: string,\n): Remote | undefined {\n for (const remote of remotes) {\n const isNameMatched = nameOrAlias === remote.name;\n if (isNameMatched) {\n return remote;\n }\n\n const isAliasMatched = remote.alias && nameOrAlias === remote.alias;\n if (isAliasMatched) {\n return remote;\n }\n }\n return;\n}\n"],"mappings":";AAEA,SAAgB,uBACd,YACA,QACQ;AACR,KAAI,CAAC,UAAU,WAAW,IACxB,QAAO;AAGT,QAAO,GAAG,WAAW,GAAG,OAAO,QAAQ,SAAS,GAAG;;AAOrD,SAAgB,6BACd,SACA,IAOY;AACZ,MAAK,MAAM,UAAU,SAAS;EAE5B,MAAM,gBAAgB,GAAG,WAAW,OAAO,KAAK;EAChD,IAAI,SAAS,GAAG,QAAQ,OAAO,MAAM,GAAG;AACxC,MAAI,eACF;OAAI,OAAO,WAAW,IAAI,EAAE;IAC1B,MAAM,iBAAiB,OAAO;AAC9B,aAAS,IAAI;AACb,WAAO;KACL;KACA;KACA;KACD;cACQ,WAAW,GACpB,QAAO;IACL,gBAAgB,OAAO;IACvB,QAAQ;IACR;IACD;;EAKL,MAAM,iBAAiB,OAAO,SAAS,GAAG,WAAW,OAAO,MAAM;EAClE,IAAI,kBAAkB,OAAO,SAAS,GAAG,QAAQ,OAAO,OAAO,GAAG;AAClE,MAAI,OAAO,SAAS,gBAClB;OAAI,mBAAmB,gBAAgB,WAAW,IAAI,EAAE;IACtD,MAAM,iBAAiB,OAAO;AAC9B,sBAAkB,IAAI;AACtB,WAAO;KACL;KACA,QAAQ;KACR;KACD;cACQ,oBAAoB,GAC7B,QAAO;IACL,gBAAgB,OAAO;IACvB,QAAQ;IACR;IACD;;;;AAST,SAAgB,YACd,SACA,aACoB;AACpB,MAAK,MAAM,UAAU,SAAS;AAE5B,MADsB,gBAAgB,OAAO,KAE3C,QAAO;AAIT,MADuB,OAAO,SAAS,gBAAgB,OAAO,MAE5D,QAAO"}
|
package/dist/utils/preload.cjs
CHANGED
|
@@ -9,7 +9,6 @@ function defaultPreloadArgs(preloadConfig) {
|
|
|
9
9
|
resourceCategory: "sync",
|
|
10
10
|
share: true,
|
|
11
11
|
depsRemote: true,
|
|
12
|
-
prefetchInterface: false,
|
|
13
12
|
...preloadConfig
|
|
14
13
|
};
|
|
15
14
|
}
|
|
@@ -34,22 +33,113 @@ function normalizePreloadExposes(exposes) {
|
|
|
34
33
|
return expose;
|
|
35
34
|
});
|
|
36
35
|
}
|
|
37
|
-
function
|
|
36
|
+
function isTimeoutError(error) {
|
|
37
|
+
if (!(error instanceof Error)) return false;
|
|
38
|
+
return error.message.includes("timed out") || error.name.includes("Timeout");
|
|
39
|
+
}
|
|
40
|
+
function createAssetResult(context, url, status, error) {
|
|
41
|
+
return {
|
|
42
|
+
url,
|
|
43
|
+
status,
|
|
44
|
+
resourceType: context.resourceType,
|
|
45
|
+
initiator: context.initiator,
|
|
46
|
+
id: context.id,
|
|
47
|
+
error
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
async function waitForRemoteEntryPreload(host, remoteInfo, entryRemoteInfo, context) {
|
|
51
|
+
const cachedRemote = host.moduleCache.get(entryRemoteInfo.name);
|
|
52
|
+
const url = entryRemoteInfo.entry;
|
|
53
|
+
if (cachedRemote?.remoteEntryExports) return createAssetResult(context, url, "cached");
|
|
54
|
+
try {
|
|
55
|
+
if (!await require_load.getRemoteEntry({
|
|
56
|
+
origin: host,
|
|
57
|
+
remoteInfo: entryRemoteInfo,
|
|
58
|
+
remoteEntryExports: cachedRemote?.remoteEntryExports,
|
|
59
|
+
resourceContext: {
|
|
60
|
+
...context,
|
|
61
|
+
url
|
|
62
|
+
}
|
|
63
|
+
})) throw new Error(`Failed to load remoteEntry "${url}".`);
|
|
64
|
+
return createAssetResult(context, url, "success");
|
|
65
|
+
} catch (error) {
|
|
66
|
+
return createAssetResult(context, url, isTimeoutError(error) ? "timeout" : "error", error);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function waitForLinkPreload({ host, remoteInfo, url, attrs, context, needDeleteLink }) {
|
|
70
|
+
return new Promise((resolve) => {
|
|
71
|
+
const { link, needAttach } = (0, _module_federation_sdk.createLink)({
|
|
72
|
+
url,
|
|
73
|
+
cb: () => {
|
|
74
|
+
resolve(createAssetResult(context, url, needAttach ? "success" : "cached"));
|
|
75
|
+
},
|
|
76
|
+
onErrorCallback: (error) => {
|
|
77
|
+
resolve(createAssetResult(context, url, isTimeoutError(error) ? "timeout" : "error", error));
|
|
78
|
+
},
|
|
79
|
+
attrs,
|
|
80
|
+
createLinkHook: (hookUrl, hookAttrs) => {
|
|
81
|
+
const res = host.loaderHook.lifecycle.createLink.emit({
|
|
82
|
+
url: hookUrl,
|
|
83
|
+
attrs: hookAttrs,
|
|
84
|
+
remoteInfo,
|
|
85
|
+
resourceContext: {
|
|
86
|
+
...context,
|
|
87
|
+
url: hookUrl
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
if (res instanceof HTMLLinkElement) return res;
|
|
91
|
+
return res;
|
|
92
|
+
},
|
|
93
|
+
needDeleteLink
|
|
94
|
+
});
|
|
95
|
+
needAttach && document.head.appendChild(link);
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
function waitForScriptPreload({ host, remoteInfo, url, attrs, context }) {
|
|
99
|
+
return new Promise((resolve) => {
|
|
100
|
+
const { script, needAttach } = (0, _module_federation_sdk.createScript)({
|
|
101
|
+
url,
|
|
102
|
+
cb: () => {
|
|
103
|
+
resolve(createAssetResult(context, url, needAttach ? "success" : "cached"));
|
|
104
|
+
},
|
|
105
|
+
onErrorCallback: (error) => {
|
|
106
|
+
resolve(createAssetResult(context, url, isTimeoutError(error) ? "timeout" : "error", error));
|
|
107
|
+
},
|
|
108
|
+
attrs,
|
|
109
|
+
createScriptHook: (hookUrl, hookAttrs) => {
|
|
110
|
+
const res = host.loaderHook.lifecycle.createScript.emit({
|
|
111
|
+
url: hookUrl,
|
|
112
|
+
attrs: hookAttrs,
|
|
113
|
+
remoteInfo,
|
|
114
|
+
resourceContext: {
|
|
115
|
+
...context,
|
|
116
|
+
url: hookUrl
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
if (res instanceof HTMLScriptElement) return res;
|
|
120
|
+
return res;
|
|
121
|
+
},
|
|
122
|
+
needDeleteScript: true
|
|
123
|
+
});
|
|
124
|
+
needAttach && document.head.appendChild(script);
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
function createResourceContext(baseContext, resourceType) {
|
|
128
|
+
return {
|
|
129
|
+
...baseContext,
|
|
130
|
+
resourceType
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
function preloadAssets(remoteInfo, host, assets, useLinkPreload = true, baseContext = {
|
|
134
|
+
initiator: "preloadRemote",
|
|
135
|
+
id: remoteInfo.name
|
|
136
|
+
}) {
|
|
38
137
|
const { cssAssets, jsAssetsWithoutEntry, entryAssets } = assets;
|
|
138
|
+
const results = [];
|
|
39
139
|
if (host.options.inBrowser) {
|
|
40
140
|
entryAssets.forEach((asset) => {
|
|
41
|
-
const { moduleInfo } = asset;
|
|
42
|
-
|
|
43
|
-
if (module) require_load.getRemoteEntry({
|
|
44
|
-
origin: host,
|
|
45
|
-
remoteInfo: moduleInfo,
|
|
46
|
-
remoteEntryExports: module.remoteEntryExports
|
|
47
|
-
});
|
|
48
|
-
else require_load.getRemoteEntry({
|
|
49
|
-
origin: host,
|
|
50
|
-
remoteInfo: moduleInfo,
|
|
51
|
-
remoteEntryExports: void 0
|
|
52
|
-
});
|
|
141
|
+
const { moduleInfo: entryRemoteInfo } = asset;
|
|
142
|
+
results.push(waitForRemoteEntryPreload(host, remoteInfo, entryRemoteInfo, createResourceContext(baseContext, "remoteEntry")));
|
|
53
143
|
});
|
|
54
144
|
if (useLinkPreload) {
|
|
55
145
|
const defaultAttrs = {
|
|
@@ -57,20 +147,13 @@ function preloadAssets(remoteInfo, host, assets, useLinkPreload = true) {
|
|
|
57
147
|
as: "style"
|
|
58
148
|
};
|
|
59
149
|
cssAssets.forEach((cssUrl) => {
|
|
60
|
-
|
|
150
|
+
results.push(waitForLinkPreload({
|
|
151
|
+
host,
|
|
152
|
+
remoteInfo,
|
|
61
153
|
url: cssUrl,
|
|
62
|
-
cb: () => {},
|
|
63
154
|
attrs: defaultAttrs,
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
url,
|
|
67
|
-
attrs,
|
|
68
|
-
remoteInfo
|
|
69
|
-
});
|
|
70
|
-
if (res instanceof HTMLLinkElement) return res;
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
needAttach && document.head.appendChild(cssEl);
|
|
155
|
+
context: createResourceContext(baseContext, "css")
|
|
156
|
+
}));
|
|
74
157
|
});
|
|
75
158
|
} else {
|
|
76
159
|
const defaultAttrs = {
|
|
@@ -78,21 +161,14 @@ function preloadAssets(remoteInfo, host, assets, useLinkPreload = true) {
|
|
|
78
161
|
type: "text/css"
|
|
79
162
|
};
|
|
80
163
|
cssAssets.forEach((cssUrl) => {
|
|
81
|
-
|
|
164
|
+
results.push(waitForLinkPreload({
|
|
165
|
+
host,
|
|
166
|
+
remoteInfo,
|
|
82
167
|
url: cssUrl,
|
|
83
|
-
cb: () => {},
|
|
84
168
|
attrs: defaultAttrs,
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
attrs,
|
|
89
|
-
remoteInfo
|
|
90
|
-
});
|
|
91
|
-
if (res instanceof HTMLLinkElement) return res;
|
|
92
|
-
},
|
|
93
|
-
needDeleteLink: false
|
|
94
|
-
});
|
|
95
|
-
needAttach && document.head.appendChild(cssEl);
|
|
169
|
+
needDeleteLink: false,
|
|
170
|
+
context: createResourceContext(baseContext, "css")
|
|
171
|
+
}));
|
|
96
172
|
});
|
|
97
173
|
}
|
|
98
174
|
if (useLinkPreload) {
|
|
@@ -101,20 +177,13 @@ function preloadAssets(remoteInfo, host, assets, useLinkPreload = true) {
|
|
|
101
177
|
as: "script"
|
|
102
178
|
};
|
|
103
179
|
jsAssetsWithoutEntry.forEach((jsUrl) => {
|
|
104
|
-
|
|
180
|
+
results.push(waitForLinkPreload({
|
|
181
|
+
host,
|
|
182
|
+
remoteInfo,
|
|
105
183
|
url: jsUrl,
|
|
106
|
-
cb: () => {},
|
|
107
184
|
attrs: defaultAttrs,
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
url,
|
|
111
|
-
attrs,
|
|
112
|
-
remoteInfo
|
|
113
|
-
});
|
|
114
|
-
if (res instanceof HTMLLinkElement) return res;
|
|
115
|
-
}
|
|
116
|
-
});
|
|
117
|
-
needAttach && document.head.appendChild(linkEl);
|
|
185
|
+
context: createResourceContext(baseContext, "js")
|
|
186
|
+
}));
|
|
118
187
|
});
|
|
119
188
|
} else {
|
|
120
189
|
const defaultAttrs = {
|
|
@@ -122,24 +191,17 @@ function preloadAssets(remoteInfo, host, assets, useLinkPreload = true) {
|
|
|
122
191
|
type: remoteInfo?.type === "module" ? "module" : "text/javascript"
|
|
123
192
|
};
|
|
124
193
|
jsAssetsWithoutEntry.forEach((jsUrl) => {
|
|
125
|
-
|
|
194
|
+
results.push(waitForScriptPreload({
|
|
195
|
+
host,
|
|
196
|
+
remoteInfo,
|
|
126
197
|
url: jsUrl,
|
|
127
|
-
cb: () => {},
|
|
128
198
|
attrs: defaultAttrs,
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
url,
|
|
132
|
-
attrs,
|
|
133
|
-
remoteInfo
|
|
134
|
-
});
|
|
135
|
-
if (res instanceof HTMLScriptElement) return res;
|
|
136
|
-
},
|
|
137
|
-
needDeleteScript: true
|
|
138
|
-
});
|
|
139
|
-
needAttach && document.head.appendChild(scriptEl);
|
|
199
|
+
context: createResourceContext(baseContext, "js")
|
|
200
|
+
}));
|
|
140
201
|
});
|
|
141
202
|
}
|
|
142
203
|
}
|
|
204
|
+
return Promise.all(results);
|
|
143
205
|
}
|
|
144
206
|
|
|
145
207
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preload.cjs","names":["matchRemote"],"sources":["../../src/utils/preload.ts"],"sourcesContent":["import { createLink, createScript, safeToString } from '@module-federation/sdk';\nimport {\n PreloadAssets,\n PreloadConfig,\n PreloadOptions,\n PreloadRemoteArgs,\n Remote,\n RemoteInfo,\n depsPreloadArg,\n} from '../type';\nimport { matchRemote } from './manifest';\nimport { assert } from './logger';\nimport { ModuleFederation } from '../core';\nimport { getRemoteEntry } from './load';\n\nexport function defaultPreloadArgs(\n preloadConfig: PreloadRemoteArgs | depsPreloadArg,\n): PreloadConfig {\n return {\n resourceCategory: 'sync',\n share: true,\n depsRemote: true,\n prefetchInterface: false,\n ...preloadConfig,\n } as PreloadConfig;\n}\n\nexport function formatPreloadArgs(\n remotes: Array<Remote>,\n preloadArgs: Array<PreloadRemoteArgs>,\n): PreloadOptions {\n return preloadArgs.map((args) => {\n const remoteInfo = matchRemote(remotes, args.nameOrAlias);\n assert(\n remoteInfo,\n `Unable to preload ${args.nameOrAlias} as it is not included in ${\n !remoteInfo &&\n safeToString({\n remoteInfo,\n remotes,\n })\n }`,\n );\n return {\n remote: remoteInfo,\n preloadConfig: defaultPreloadArgs(args),\n };\n });\n}\n\nexport function normalizePreloadExposes(exposes?: string[]): string[] {\n if (!exposes) {\n return [];\n }\n\n return exposes.map((expose) => {\n if (expose === '.') {\n return expose;\n }\n if (expose.startsWith('./')) {\n return expose.replace('./', '');\n }\n return expose;\n });\n}\n\nexport function preloadAssets(\n remoteInfo: RemoteInfo,\n host: ModuleFederation,\n assets: PreloadAssets,\n // It is used to distinguish preload from load remote parallel loading\n useLinkPreload = true,\n): void {\n const { cssAssets, jsAssetsWithoutEntry, entryAssets } = assets;\n\n if (host.options.inBrowser) {\n entryAssets.forEach((asset) => {\n const { moduleInfo } = asset;\n const module = host.moduleCache.get(remoteInfo.name);\n if (module) {\n getRemoteEntry({\n origin: host,\n remoteInfo: moduleInfo,\n remoteEntryExports: module.remoteEntryExports,\n });\n } else {\n getRemoteEntry({\n origin: host,\n remoteInfo: moduleInfo,\n remoteEntryExports: undefined,\n });\n }\n });\n\n if (useLinkPreload) {\n const defaultAttrs = {\n rel: 'preload',\n as: 'style',\n };\n cssAssets.forEach((cssUrl) => {\n const { link: cssEl, needAttach } = createLink({\n url: cssUrl,\n cb: () => {\n // noop\n },\n attrs: defaultAttrs,\n createLinkHook: (url, attrs) => {\n const res = host.loaderHook.lifecycle.createLink.emit({\n url,\n attrs,\n remoteInfo,\n });\n if (res instanceof HTMLLinkElement) {\n return res;\n }\n return;\n },\n });\n\n needAttach && document.head.appendChild(cssEl);\n });\n } else {\n const defaultAttrs = {\n rel: 'stylesheet',\n type: 'text/css',\n };\n cssAssets.forEach((cssUrl) => {\n const { link: cssEl, needAttach } = createLink({\n url: cssUrl,\n cb: () => {\n // noop\n },\n attrs: defaultAttrs,\n createLinkHook: (url, attrs) => {\n const res = host.loaderHook.lifecycle.createLink.emit({\n url,\n attrs,\n remoteInfo,\n });\n if (res instanceof HTMLLinkElement) {\n return res;\n }\n return;\n },\n needDeleteLink: false,\n });\n\n needAttach && document.head.appendChild(cssEl);\n });\n }\n\n if (useLinkPreload) {\n const defaultAttrs = {\n rel: 'preload',\n as: 'script',\n };\n jsAssetsWithoutEntry.forEach((jsUrl) => {\n const { link: linkEl, needAttach } = createLink({\n url: jsUrl,\n cb: () => {\n // noop\n },\n attrs: defaultAttrs,\n createLinkHook: (url: string, attrs) => {\n const res = host.loaderHook.lifecycle.createLink.emit({\n url,\n attrs,\n remoteInfo,\n });\n if (res instanceof HTMLLinkElement) {\n return res;\n }\n return;\n },\n });\n needAttach && document.head.appendChild(linkEl);\n });\n } else {\n const defaultAttrs = {\n fetchpriority: 'high',\n type: remoteInfo?.type === 'module' ? 'module' : 'text/javascript',\n };\n jsAssetsWithoutEntry.forEach((jsUrl) => {\n const { script: scriptEl, needAttach } = createScript({\n url: jsUrl,\n cb: () => {\n // noop\n },\n attrs: defaultAttrs,\n createScriptHook: (url: string, attrs: any) => {\n const res = host.loaderHook.lifecycle.createScript.emit({\n url,\n attrs,\n remoteInfo,\n });\n if (res instanceof HTMLScriptElement) {\n return res;\n }\n return;\n },\n needDeleteScript: true,\n });\n needAttach && document.head.appendChild(scriptEl);\n });\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"preload.cjs","names":["matchRemote","getRemoteEntry"],"sources":["../../src/utils/preload.ts"],"sourcesContent":["import { createLink, createScript, safeToString } from '@module-federation/sdk';\nimport {\n PreloadAssets,\n PreloadAssetResult,\n PreloadConfig,\n PreloadOptions,\n PreloadRemoteArgs,\n Remote,\n RemoteInfo,\n ResourceLoadContext,\n ResourceLoadType,\n depsPreloadArg,\n} from '../type';\nimport { matchRemote } from './manifest';\nimport { assert } from './logger';\nimport { ModuleFederation } from '../core';\nimport { getRemoteEntry } from './load';\n\nexport function defaultPreloadArgs(\n preloadConfig: PreloadRemoteArgs | depsPreloadArg,\n): PreloadConfig {\n return {\n resourceCategory: 'sync',\n share: true,\n depsRemote: true,\n ...preloadConfig,\n } as PreloadConfig;\n}\n\nexport function formatPreloadArgs(\n remotes: Array<Remote>,\n preloadArgs: Array<PreloadRemoteArgs>,\n): PreloadOptions {\n return preloadArgs.map((args) => {\n const remoteInfo = matchRemote(remotes, args.nameOrAlias);\n assert(\n remoteInfo,\n `Unable to preload ${args.nameOrAlias} as it is not included in ${\n !remoteInfo &&\n safeToString({\n remoteInfo,\n remotes,\n })\n }`,\n );\n return {\n remote: remoteInfo,\n preloadConfig: defaultPreloadArgs(args),\n };\n });\n}\n\nexport function normalizePreloadExposes(exposes?: string[]): string[] {\n if (!exposes) {\n return [];\n }\n\n return exposes.map((expose) => {\n if (expose === '.') {\n return expose;\n }\n if (expose.startsWith('./')) {\n return expose.replace('./', '');\n }\n return expose;\n });\n}\n\nfunction isTimeoutError(error: unknown): boolean {\n if (!(error instanceof Error)) {\n return false;\n }\n return error.message.includes('timed out') || error.name.includes('Timeout');\n}\n\nfunction createAssetResult(\n context: ResourceLoadContext,\n url: string,\n status: PreloadAssetResult['status'],\n error?: unknown,\n): PreloadAssetResult {\n return {\n url,\n status,\n resourceType: context.resourceType,\n initiator: context.initiator,\n id: context.id,\n error,\n };\n}\n\nasync function waitForRemoteEntryPreload(\n host: ModuleFederation,\n remoteInfo: RemoteInfo,\n entryRemoteInfo: RemoteInfo,\n context: ResourceLoadContext,\n): Promise<PreloadAssetResult> {\n const cachedRemote = host.moduleCache.get(entryRemoteInfo.name);\n const url = entryRemoteInfo.entry;\n if (cachedRemote?.remoteEntryExports) {\n return createAssetResult(context, url, 'cached');\n }\n\n try {\n const remoteEntryExports = await getRemoteEntry({\n origin: host,\n remoteInfo: entryRemoteInfo,\n remoteEntryExports: cachedRemote?.remoteEntryExports,\n resourceContext: {\n ...context,\n url,\n },\n });\n if (!remoteEntryExports) {\n throw new Error(`Failed to load remoteEntry \"${url}\".`);\n }\n return createAssetResult(context, url, 'success');\n } catch (error) {\n return createAssetResult(\n context,\n url,\n isTimeoutError(error) ? 'timeout' : 'error',\n error,\n );\n }\n}\n\nfunction waitForLinkPreload({\n host,\n remoteInfo,\n url,\n attrs,\n context,\n needDeleteLink,\n}: {\n host: ModuleFederation;\n remoteInfo: RemoteInfo;\n url: string;\n attrs: Record<string, string>;\n context: ResourceLoadContext;\n needDeleteLink?: boolean;\n}): Promise<PreloadAssetResult> {\n return new Promise((resolve) => {\n const { link, needAttach } = createLink({\n url,\n cb: () => {\n resolve(\n createAssetResult(context, url, needAttach ? 'success' : 'cached'),\n );\n },\n onErrorCallback: (error) => {\n resolve(\n createAssetResult(\n context,\n url,\n isTimeoutError(error) ? 'timeout' : 'error',\n error,\n ),\n );\n },\n attrs,\n createLinkHook: (hookUrl, hookAttrs) => {\n const res = host.loaderHook.lifecycle.createLink.emit({\n url: hookUrl,\n attrs: hookAttrs,\n remoteInfo,\n resourceContext: {\n ...context,\n url: hookUrl,\n },\n });\n if (res instanceof HTMLLinkElement) {\n return res;\n }\n return res;\n },\n needDeleteLink,\n });\n\n needAttach && document.head.appendChild(link);\n });\n}\n\nfunction waitForScriptPreload({\n host,\n remoteInfo,\n url,\n attrs,\n context,\n}: {\n host: ModuleFederation;\n remoteInfo: RemoteInfo;\n url: string;\n attrs: Record<string, string>;\n context: ResourceLoadContext;\n}): Promise<PreloadAssetResult> {\n return new Promise((resolve) => {\n const { script, needAttach } = createScript({\n url,\n cb: () => {\n resolve(\n createAssetResult(context, url, needAttach ? 'success' : 'cached'),\n );\n },\n onErrorCallback: (error) => {\n resolve(\n createAssetResult(\n context,\n url,\n isTimeoutError(error) ? 'timeout' : 'error',\n error,\n ),\n );\n },\n attrs,\n createScriptHook: (hookUrl: string, hookAttrs: any) => {\n const res = host.loaderHook.lifecycle.createScript.emit({\n url: hookUrl,\n attrs: hookAttrs,\n remoteInfo,\n resourceContext: {\n ...context,\n url: hookUrl,\n },\n });\n if (res instanceof HTMLScriptElement) {\n return res;\n }\n return res;\n },\n needDeleteScript: true,\n });\n\n needAttach && document.head.appendChild(script);\n });\n}\n\nfunction createResourceContext(\n baseContext: Omit<ResourceLoadContext, 'resourceType'>,\n resourceType: ResourceLoadType,\n): ResourceLoadContext {\n return {\n ...baseContext,\n resourceType,\n };\n}\n\nexport function preloadAssets(\n remoteInfo: RemoteInfo,\n host: ModuleFederation,\n assets: PreloadAssets,\n // It is used to distinguish preload from load remote parallel loading\n useLinkPreload = true,\n baseContext: Omit<ResourceLoadContext, 'resourceType'> = {\n initiator: 'preloadRemote',\n id: remoteInfo.name,\n },\n): Promise<PreloadAssetResult[]> {\n const { cssAssets, jsAssetsWithoutEntry, entryAssets } = assets;\n const results: Array<Promise<PreloadAssetResult>> = [];\n\n if (host.options.inBrowser) {\n entryAssets.forEach((asset) => {\n const { moduleInfo: entryRemoteInfo } = asset;\n results.push(\n waitForRemoteEntryPreload(\n host,\n remoteInfo,\n entryRemoteInfo,\n createResourceContext(baseContext, 'remoteEntry'),\n ),\n );\n });\n\n if (useLinkPreload) {\n const defaultAttrs = {\n rel: 'preload',\n as: 'style',\n };\n cssAssets.forEach((cssUrl) => {\n results.push(\n waitForLinkPreload({\n host,\n remoteInfo,\n url: cssUrl,\n attrs: defaultAttrs,\n context: createResourceContext(baseContext, 'css'),\n }),\n );\n });\n } else {\n const defaultAttrs = {\n rel: 'stylesheet',\n type: 'text/css',\n };\n cssAssets.forEach((cssUrl) => {\n results.push(\n waitForLinkPreload({\n host,\n remoteInfo,\n url: cssUrl,\n attrs: defaultAttrs,\n needDeleteLink: false,\n context: createResourceContext(baseContext, 'css'),\n }),\n );\n });\n }\n\n if (useLinkPreload) {\n const defaultAttrs = {\n rel: 'preload',\n as: 'script',\n };\n jsAssetsWithoutEntry.forEach((jsUrl) => {\n results.push(\n waitForLinkPreload({\n host,\n remoteInfo,\n url: jsUrl,\n attrs: defaultAttrs,\n context: createResourceContext(baseContext, 'js'),\n }),\n );\n });\n } else {\n const defaultAttrs = {\n fetchpriority: 'high',\n type: remoteInfo?.type === 'module' ? 'module' : 'text/javascript',\n };\n jsAssetsWithoutEntry.forEach((jsUrl) => {\n results.push(\n waitForScriptPreload({\n host,\n remoteInfo,\n url: jsUrl,\n attrs: defaultAttrs,\n context: createResourceContext(baseContext, 'js'),\n }),\n );\n });\n }\n }\n\n return Promise.all(results);\n}\n"],"mappings":"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"}
|
package/dist/utils/preload.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { ModuleFederation } from "../core.js";
|
|
2
2
|
import { RemoteInfo } from "../type/config.js";
|
|
3
|
-
import { PreloadAssets } from "../type/preload.js";
|
|
3
|
+
import { PreloadAssetResult, PreloadAssets, ResourceLoadContext } from "../type/preload.js";
|
|
4
4
|
//#region src/utils/preload.d.ts
|
|
5
|
-
declare function preloadAssets(remoteInfo: RemoteInfo, host: ModuleFederation, assets: PreloadAssets, useLinkPreload?: boolean):
|
|
5
|
+
declare function preloadAssets(remoteInfo: RemoteInfo, host: ModuleFederation, assets: PreloadAssets, useLinkPreload?: boolean, baseContext?: Omit<ResourceLoadContext, 'resourceType'>): Promise<PreloadAssetResult[]>;
|
|
6
6
|
//#endregion
|
|
7
7
|
export { preloadAssets };
|
|
8
8
|
//# sourceMappingURL=preload.d.ts.map
|
package/dist/utils/preload.js
CHANGED
|
@@ -9,7 +9,6 @@ function defaultPreloadArgs(preloadConfig) {
|
|
|
9
9
|
resourceCategory: "sync",
|
|
10
10
|
share: true,
|
|
11
11
|
depsRemote: true,
|
|
12
|
-
prefetchInterface: false,
|
|
13
12
|
...preloadConfig
|
|
14
13
|
};
|
|
15
14
|
}
|
|
@@ -34,22 +33,113 @@ function normalizePreloadExposes(exposes) {
|
|
|
34
33
|
return expose;
|
|
35
34
|
});
|
|
36
35
|
}
|
|
37
|
-
function
|
|
36
|
+
function isTimeoutError(error) {
|
|
37
|
+
if (!(error instanceof Error)) return false;
|
|
38
|
+
return error.message.includes("timed out") || error.name.includes("Timeout");
|
|
39
|
+
}
|
|
40
|
+
function createAssetResult(context, url, status, error) {
|
|
41
|
+
return {
|
|
42
|
+
url,
|
|
43
|
+
status,
|
|
44
|
+
resourceType: context.resourceType,
|
|
45
|
+
initiator: context.initiator,
|
|
46
|
+
id: context.id,
|
|
47
|
+
error
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
async function waitForRemoteEntryPreload(host, remoteInfo, entryRemoteInfo, context) {
|
|
51
|
+
const cachedRemote = host.moduleCache.get(entryRemoteInfo.name);
|
|
52
|
+
const url = entryRemoteInfo.entry;
|
|
53
|
+
if (cachedRemote?.remoteEntryExports) return createAssetResult(context, url, "cached");
|
|
54
|
+
try {
|
|
55
|
+
if (!await getRemoteEntry({
|
|
56
|
+
origin: host,
|
|
57
|
+
remoteInfo: entryRemoteInfo,
|
|
58
|
+
remoteEntryExports: cachedRemote?.remoteEntryExports,
|
|
59
|
+
resourceContext: {
|
|
60
|
+
...context,
|
|
61
|
+
url
|
|
62
|
+
}
|
|
63
|
+
})) throw new Error(`Failed to load remoteEntry "${url}".`);
|
|
64
|
+
return createAssetResult(context, url, "success");
|
|
65
|
+
} catch (error) {
|
|
66
|
+
return createAssetResult(context, url, isTimeoutError(error) ? "timeout" : "error", error);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function waitForLinkPreload({ host, remoteInfo, url, attrs, context, needDeleteLink }) {
|
|
70
|
+
return new Promise((resolve) => {
|
|
71
|
+
const { link, needAttach } = createLink({
|
|
72
|
+
url,
|
|
73
|
+
cb: () => {
|
|
74
|
+
resolve(createAssetResult(context, url, needAttach ? "success" : "cached"));
|
|
75
|
+
},
|
|
76
|
+
onErrorCallback: (error) => {
|
|
77
|
+
resolve(createAssetResult(context, url, isTimeoutError(error) ? "timeout" : "error", error));
|
|
78
|
+
},
|
|
79
|
+
attrs,
|
|
80
|
+
createLinkHook: (hookUrl, hookAttrs) => {
|
|
81
|
+
const res = host.loaderHook.lifecycle.createLink.emit({
|
|
82
|
+
url: hookUrl,
|
|
83
|
+
attrs: hookAttrs,
|
|
84
|
+
remoteInfo,
|
|
85
|
+
resourceContext: {
|
|
86
|
+
...context,
|
|
87
|
+
url: hookUrl
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
if (res instanceof HTMLLinkElement) return res;
|
|
91
|
+
return res;
|
|
92
|
+
},
|
|
93
|
+
needDeleteLink
|
|
94
|
+
});
|
|
95
|
+
needAttach && document.head.appendChild(link);
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
function waitForScriptPreload({ host, remoteInfo, url, attrs, context }) {
|
|
99
|
+
return new Promise((resolve) => {
|
|
100
|
+
const { script, needAttach } = createScript({
|
|
101
|
+
url,
|
|
102
|
+
cb: () => {
|
|
103
|
+
resolve(createAssetResult(context, url, needAttach ? "success" : "cached"));
|
|
104
|
+
},
|
|
105
|
+
onErrorCallback: (error) => {
|
|
106
|
+
resolve(createAssetResult(context, url, isTimeoutError(error) ? "timeout" : "error", error));
|
|
107
|
+
},
|
|
108
|
+
attrs,
|
|
109
|
+
createScriptHook: (hookUrl, hookAttrs) => {
|
|
110
|
+
const res = host.loaderHook.lifecycle.createScript.emit({
|
|
111
|
+
url: hookUrl,
|
|
112
|
+
attrs: hookAttrs,
|
|
113
|
+
remoteInfo,
|
|
114
|
+
resourceContext: {
|
|
115
|
+
...context,
|
|
116
|
+
url: hookUrl
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
if (res instanceof HTMLScriptElement) return res;
|
|
120
|
+
return res;
|
|
121
|
+
},
|
|
122
|
+
needDeleteScript: true
|
|
123
|
+
});
|
|
124
|
+
needAttach && document.head.appendChild(script);
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
function createResourceContext(baseContext, resourceType) {
|
|
128
|
+
return {
|
|
129
|
+
...baseContext,
|
|
130
|
+
resourceType
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
function preloadAssets(remoteInfo, host, assets, useLinkPreload = true, baseContext = {
|
|
134
|
+
initiator: "preloadRemote",
|
|
135
|
+
id: remoteInfo.name
|
|
136
|
+
}) {
|
|
38
137
|
const { cssAssets, jsAssetsWithoutEntry, entryAssets } = assets;
|
|
138
|
+
const results = [];
|
|
39
139
|
if (host.options.inBrowser) {
|
|
40
140
|
entryAssets.forEach((asset) => {
|
|
41
|
-
const { moduleInfo } = asset;
|
|
42
|
-
|
|
43
|
-
if (module) getRemoteEntry({
|
|
44
|
-
origin: host,
|
|
45
|
-
remoteInfo: moduleInfo,
|
|
46
|
-
remoteEntryExports: module.remoteEntryExports
|
|
47
|
-
});
|
|
48
|
-
else getRemoteEntry({
|
|
49
|
-
origin: host,
|
|
50
|
-
remoteInfo: moduleInfo,
|
|
51
|
-
remoteEntryExports: void 0
|
|
52
|
-
});
|
|
141
|
+
const { moduleInfo: entryRemoteInfo } = asset;
|
|
142
|
+
results.push(waitForRemoteEntryPreload(host, remoteInfo, entryRemoteInfo, createResourceContext(baseContext, "remoteEntry")));
|
|
53
143
|
});
|
|
54
144
|
if (useLinkPreload) {
|
|
55
145
|
const defaultAttrs = {
|
|
@@ -57,20 +147,13 @@ function preloadAssets(remoteInfo, host, assets, useLinkPreload = true) {
|
|
|
57
147
|
as: "style"
|
|
58
148
|
};
|
|
59
149
|
cssAssets.forEach((cssUrl) => {
|
|
60
|
-
|
|
150
|
+
results.push(waitForLinkPreload({
|
|
151
|
+
host,
|
|
152
|
+
remoteInfo,
|
|
61
153
|
url: cssUrl,
|
|
62
|
-
cb: () => {},
|
|
63
154
|
attrs: defaultAttrs,
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
url,
|
|
67
|
-
attrs,
|
|
68
|
-
remoteInfo
|
|
69
|
-
});
|
|
70
|
-
if (res instanceof HTMLLinkElement) return res;
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
needAttach && document.head.appendChild(cssEl);
|
|
155
|
+
context: createResourceContext(baseContext, "css")
|
|
156
|
+
}));
|
|
74
157
|
});
|
|
75
158
|
} else {
|
|
76
159
|
const defaultAttrs = {
|
|
@@ -78,21 +161,14 @@ function preloadAssets(remoteInfo, host, assets, useLinkPreload = true) {
|
|
|
78
161
|
type: "text/css"
|
|
79
162
|
};
|
|
80
163
|
cssAssets.forEach((cssUrl) => {
|
|
81
|
-
|
|
164
|
+
results.push(waitForLinkPreload({
|
|
165
|
+
host,
|
|
166
|
+
remoteInfo,
|
|
82
167
|
url: cssUrl,
|
|
83
|
-
cb: () => {},
|
|
84
168
|
attrs: defaultAttrs,
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
attrs,
|
|
89
|
-
remoteInfo
|
|
90
|
-
});
|
|
91
|
-
if (res instanceof HTMLLinkElement) return res;
|
|
92
|
-
},
|
|
93
|
-
needDeleteLink: false
|
|
94
|
-
});
|
|
95
|
-
needAttach && document.head.appendChild(cssEl);
|
|
169
|
+
needDeleteLink: false,
|
|
170
|
+
context: createResourceContext(baseContext, "css")
|
|
171
|
+
}));
|
|
96
172
|
});
|
|
97
173
|
}
|
|
98
174
|
if (useLinkPreload) {
|
|
@@ -101,20 +177,13 @@ function preloadAssets(remoteInfo, host, assets, useLinkPreload = true) {
|
|
|
101
177
|
as: "script"
|
|
102
178
|
};
|
|
103
179
|
jsAssetsWithoutEntry.forEach((jsUrl) => {
|
|
104
|
-
|
|
180
|
+
results.push(waitForLinkPreload({
|
|
181
|
+
host,
|
|
182
|
+
remoteInfo,
|
|
105
183
|
url: jsUrl,
|
|
106
|
-
cb: () => {},
|
|
107
184
|
attrs: defaultAttrs,
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
url,
|
|
111
|
-
attrs,
|
|
112
|
-
remoteInfo
|
|
113
|
-
});
|
|
114
|
-
if (res instanceof HTMLLinkElement) return res;
|
|
115
|
-
}
|
|
116
|
-
});
|
|
117
|
-
needAttach && document.head.appendChild(linkEl);
|
|
185
|
+
context: createResourceContext(baseContext, "js")
|
|
186
|
+
}));
|
|
118
187
|
});
|
|
119
188
|
} else {
|
|
120
189
|
const defaultAttrs = {
|
|
@@ -122,24 +191,17 @@ function preloadAssets(remoteInfo, host, assets, useLinkPreload = true) {
|
|
|
122
191
|
type: remoteInfo?.type === "module" ? "module" : "text/javascript"
|
|
123
192
|
};
|
|
124
193
|
jsAssetsWithoutEntry.forEach((jsUrl) => {
|
|
125
|
-
|
|
194
|
+
results.push(waitForScriptPreload({
|
|
195
|
+
host,
|
|
196
|
+
remoteInfo,
|
|
126
197
|
url: jsUrl,
|
|
127
|
-
cb: () => {},
|
|
128
198
|
attrs: defaultAttrs,
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
url,
|
|
132
|
-
attrs,
|
|
133
|
-
remoteInfo
|
|
134
|
-
});
|
|
135
|
-
if (res instanceof HTMLScriptElement) return res;
|
|
136
|
-
},
|
|
137
|
-
needDeleteScript: true
|
|
138
|
-
});
|
|
139
|
-
needAttach && document.head.appendChild(scriptEl);
|
|
199
|
+
context: createResourceContext(baseContext, "js")
|
|
200
|
+
}));
|
|
140
201
|
});
|
|
141
202
|
}
|
|
142
203
|
}
|
|
204
|
+
return Promise.all(results);
|
|
143
205
|
}
|
|
144
206
|
|
|
145
207
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preload.js","names":[],"sources":["../../src/utils/preload.ts"],"sourcesContent":["import { createLink, createScript, safeToString } from '@module-federation/sdk';\nimport {\n PreloadAssets,\n PreloadConfig,\n PreloadOptions,\n PreloadRemoteArgs,\n Remote,\n RemoteInfo,\n depsPreloadArg,\n} from '../type';\nimport { matchRemote } from './manifest';\nimport { assert } from './logger';\nimport { ModuleFederation } from '../core';\nimport { getRemoteEntry } from './load';\n\nexport function defaultPreloadArgs(\n preloadConfig: PreloadRemoteArgs | depsPreloadArg,\n): PreloadConfig {\n return {\n resourceCategory: 'sync',\n share: true,\n depsRemote: true,\n prefetchInterface: false,\n ...preloadConfig,\n } as PreloadConfig;\n}\n\nexport function formatPreloadArgs(\n remotes: Array<Remote>,\n preloadArgs: Array<PreloadRemoteArgs>,\n): PreloadOptions {\n return preloadArgs.map((args) => {\n const remoteInfo = matchRemote(remotes, args.nameOrAlias);\n assert(\n remoteInfo,\n `Unable to preload ${args.nameOrAlias} as it is not included in ${\n !remoteInfo &&\n safeToString({\n remoteInfo,\n remotes,\n })\n }`,\n );\n return {\n remote: remoteInfo,\n preloadConfig: defaultPreloadArgs(args),\n };\n });\n}\n\nexport function normalizePreloadExposes(exposes?: string[]): string[] {\n if (!exposes) {\n return [];\n }\n\n return exposes.map((expose) => {\n if (expose === '.') {\n return expose;\n }\n if (expose.startsWith('./')) {\n return expose.replace('./', '');\n }\n return expose;\n });\n}\n\nexport function preloadAssets(\n remoteInfo: RemoteInfo,\n host: ModuleFederation,\n assets: PreloadAssets,\n // It is used to distinguish preload from load remote parallel loading\n useLinkPreload = true,\n): void {\n const { cssAssets, jsAssetsWithoutEntry, entryAssets } = assets;\n\n if (host.options.inBrowser) {\n entryAssets.forEach((asset) => {\n const { moduleInfo } = asset;\n const module = host.moduleCache.get(remoteInfo.name);\n if (module) {\n getRemoteEntry({\n origin: host,\n remoteInfo: moduleInfo,\n remoteEntryExports: module.remoteEntryExports,\n });\n } else {\n getRemoteEntry({\n origin: host,\n remoteInfo: moduleInfo,\n remoteEntryExports: undefined,\n });\n }\n });\n\n if (useLinkPreload) {\n const defaultAttrs = {\n rel: 'preload',\n as: 'style',\n };\n cssAssets.forEach((cssUrl) => {\n const { link: cssEl, needAttach } = createLink({\n url: cssUrl,\n cb: () => {\n // noop\n },\n attrs: defaultAttrs,\n createLinkHook: (url, attrs) => {\n const res = host.loaderHook.lifecycle.createLink.emit({\n url,\n attrs,\n remoteInfo,\n });\n if (res instanceof HTMLLinkElement) {\n return res;\n }\n return;\n },\n });\n\n needAttach && document.head.appendChild(cssEl);\n });\n } else {\n const defaultAttrs = {\n rel: 'stylesheet',\n type: 'text/css',\n };\n cssAssets.forEach((cssUrl) => {\n const { link: cssEl, needAttach } = createLink({\n url: cssUrl,\n cb: () => {\n // noop\n },\n attrs: defaultAttrs,\n createLinkHook: (url, attrs) => {\n const res = host.loaderHook.lifecycle.createLink.emit({\n url,\n attrs,\n remoteInfo,\n });\n if (res instanceof HTMLLinkElement) {\n return res;\n }\n return;\n },\n needDeleteLink: false,\n });\n\n needAttach && document.head.appendChild(cssEl);\n });\n }\n\n if (useLinkPreload) {\n const defaultAttrs = {\n rel: 'preload',\n as: 'script',\n };\n jsAssetsWithoutEntry.forEach((jsUrl) => {\n const { link: linkEl, needAttach } = createLink({\n url: jsUrl,\n cb: () => {\n // noop\n },\n attrs: defaultAttrs,\n createLinkHook: (url: string, attrs) => {\n const res = host.loaderHook.lifecycle.createLink.emit({\n url,\n attrs,\n remoteInfo,\n });\n if (res instanceof HTMLLinkElement) {\n return res;\n }\n return;\n },\n });\n needAttach && document.head.appendChild(linkEl);\n });\n } else {\n const defaultAttrs = {\n fetchpriority: 'high',\n type: remoteInfo?.type === 'module' ? 'module' : 'text/javascript',\n };\n jsAssetsWithoutEntry.forEach((jsUrl) => {\n const { script: scriptEl, needAttach } = createScript({\n url: jsUrl,\n cb: () => {\n // noop\n },\n attrs: defaultAttrs,\n createScriptHook: (url: string, attrs: any) => {\n const res = host.loaderHook.lifecycle.createScript.emit({\n url,\n attrs,\n remoteInfo,\n });\n if (res instanceof HTMLScriptElement) {\n return res;\n }\n return;\n },\n needDeleteScript: true,\n });\n needAttach && document.head.appendChild(scriptEl);\n });\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"preload.js","names":[],"sources":["../../src/utils/preload.ts"],"sourcesContent":["import { createLink, createScript, safeToString } from '@module-federation/sdk';\nimport {\n PreloadAssets,\n PreloadAssetResult,\n PreloadConfig,\n PreloadOptions,\n PreloadRemoteArgs,\n Remote,\n RemoteInfo,\n ResourceLoadContext,\n ResourceLoadType,\n depsPreloadArg,\n} from '../type';\nimport { matchRemote } from './manifest';\nimport { assert } from './logger';\nimport { ModuleFederation } from '../core';\nimport { getRemoteEntry } from './load';\n\nexport function defaultPreloadArgs(\n preloadConfig: PreloadRemoteArgs | depsPreloadArg,\n): PreloadConfig {\n return {\n resourceCategory: 'sync',\n share: true,\n depsRemote: true,\n ...preloadConfig,\n } as PreloadConfig;\n}\n\nexport function formatPreloadArgs(\n remotes: Array<Remote>,\n preloadArgs: Array<PreloadRemoteArgs>,\n): PreloadOptions {\n return preloadArgs.map((args) => {\n const remoteInfo = matchRemote(remotes, args.nameOrAlias);\n assert(\n remoteInfo,\n `Unable to preload ${args.nameOrAlias} as it is not included in ${\n !remoteInfo &&\n safeToString({\n remoteInfo,\n remotes,\n })\n }`,\n );\n return {\n remote: remoteInfo,\n preloadConfig: defaultPreloadArgs(args),\n };\n });\n}\n\nexport function normalizePreloadExposes(exposes?: string[]): string[] {\n if (!exposes) {\n return [];\n }\n\n return exposes.map((expose) => {\n if (expose === '.') {\n return expose;\n }\n if (expose.startsWith('./')) {\n return expose.replace('./', '');\n }\n return expose;\n });\n}\n\nfunction isTimeoutError(error: unknown): boolean {\n if (!(error instanceof Error)) {\n return false;\n }\n return error.message.includes('timed out') || error.name.includes('Timeout');\n}\n\nfunction createAssetResult(\n context: ResourceLoadContext,\n url: string,\n status: PreloadAssetResult['status'],\n error?: unknown,\n): PreloadAssetResult {\n return {\n url,\n status,\n resourceType: context.resourceType,\n initiator: context.initiator,\n id: context.id,\n error,\n };\n}\n\nasync function waitForRemoteEntryPreload(\n host: ModuleFederation,\n remoteInfo: RemoteInfo,\n entryRemoteInfo: RemoteInfo,\n context: ResourceLoadContext,\n): Promise<PreloadAssetResult> {\n const cachedRemote = host.moduleCache.get(entryRemoteInfo.name);\n const url = entryRemoteInfo.entry;\n if (cachedRemote?.remoteEntryExports) {\n return createAssetResult(context, url, 'cached');\n }\n\n try {\n const remoteEntryExports = await getRemoteEntry({\n origin: host,\n remoteInfo: entryRemoteInfo,\n remoteEntryExports: cachedRemote?.remoteEntryExports,\n resourceContext: {\n ...context,\n url,\n },\n });\n if (!remoteEntryExports) {\n throw new Error(`Failed to load remoteEntry \"${url}\".`);\n }\n return createAssetResult(context, url, 'success');\n } catch (error) {\n return createAssetResult(\n context,\n url,\n isTimeoutError(error) ? 'timeout' : 'error',\n error,\n );\n }\n}\n\nfunction waitForLinkPreload({\n host,\n remoteInfo,\n url,\n attrs,\n context,\n needDeleteLink,\n}: {\n host: ModuleFederation;\n remoteInfo: RemoteInfo;\n url: string;\n attrs: Record<string, string>;\n context: ResourceLoadContext;\n needDeleteLink?: boolean;\n}): Promise<PreloadAssetResult> {\n return new Promise((resolve) => {\n const { link, needAttach } = createLink({\n url,\n cb: () => {\n resolve(\n createAssetResult(context, url, needAttach ? 'success' : 'cached'),\n );\n },\n onErrorCallback: (error) => {\n resolve(\n createAssetResult(\n context,\n url,\n isTimeoutError(error) ? 'timeout' : 'error',\n error,\n ),\n );\n },\n attrs,\n createLinkHook: (hookUrl, hookAttrs) => {\n const res = host.loaderHook.lifecycle.createLink.emit({\n url: hookUrl,\n attrs: hookAttrs,\n remoteInfo,\n resourceContext: {\n ...context,\n url: hookUrl,\n },\n });\n if (res instanceof HTMLLinkElement) {\n return res;\n }\n return res;\n },\n needDeleteLink,\n });\n\n needAttach && document.head.appendChild(link);\n });\n}\n\nfunction waitForScriptPreload({\n host,\n remoteInfo,\n url,\n attrs,\n context,\n}: {\n host: ModuleFederation;\n remoteInfo: RemoteInfo;\n url: string;\n attrs: Record<string, string>;\n context: ResourceLoadContext;\n}): Promise<PreloadAssetResult> {\n return new Promise((resolve) => {\n const { script, needAttach } = createScript({\n url,\n cb: () => {\n resolve(\n createAssetResult(context, url, needAttach ? 'success' : 'cached'),\n );\n },\n onErrorCallback: (error) => {\n resolve(\n createAssetResult(\n context,\n url,\n isTimeoutError(error) ? 'timeout' : 'error',\n error,\n ),\n );\n },\n attrs,\n createScriptHook: (hookUrl: string, hookAttrs: any) => {\n const res = host.loaderHook.lifecycle.createScript.emit({\n url: hookUrl,\n attrs: hookAttrs,\n remoteInfo,\n resourceContext: {\n ...context,\n url: hookUrl,\n },\n });\n if (res instanceof HTMLScriptElement) {\n return res;\n }\n return res;\n },\n needDeleteScript: true,\n });\n\n needAttach && document.head.appendChild(script);\n });\n}\n\nfunction createResourceContext(\n baseContext: Omit<ResourceLoadContext, 'resourceType'>,\n resourceType: ResourceLoadType,\n): ResourceLoadContext {\n return {\n ...baseContext,\n resourceType,\n };\n}\n\nexport function preloadAssets(\n remoteInfo: RemoteInfo,\n host: ModuleFederation,\n assets: PreloadAssets,\n // It is used to distinguish preload from load remote parallel loading\n useLinkPreload = true,\n baseContext: Omit<ResourceLoadContext, 'resourceType'> = {\n initiator: 'preloadRemote',\n id: remoteInfo.name,\n },\n): Promise<PreloadAssetResult[]> {\n const { cssAssets, jsAssetsWithoutEntry, entryAssets } = assets;\n const results: Array<Promise<PreloadAssetResult>> = [];\n\n if (host.options.inBrowser) {\n entryAssets.forEach((asset) => {\n const { moduleInfo: entryRemoteInfo } = asset;\n results.push(\n waitForRemoteEntryPreload(\n host,\n remoteInfo,\n entryRemoteInfo,\n createResourceContext(baseContext, 'remoteEntry'),\n ),\n );\n });\n\n if (useLinkPreload) {\n const defaultAttrs = {\n rel: 'preload',\n as: 'style',\n };\n cssAssets.forEach((cssUrl) => {\n results.push(\n waitForLinkPreload({\n host,\n remoteInfo,\n url: cssUrl,\n attrs: defaultAttrs,\n context: createResourceContext(baseContext, 'css'),\n }),\n );\n });\n } else {\n const defaultAttrs = {\n rel: 'stylesheet',\n type: 'text/css',\n };\n cssAssets.forEach((cssUrl) => {\n results.push(\n waitForLinkPreload({\n host,\n remoteInfo,\n url: cssUrl,\n attrs: defaultAttrs,\n needDeleteLink: false,\n context: createResourceContext(baseContext, 'css'),\n }),\n );\n });\n }\n\n if (useLinkPreload) {\n const defaultAttrs = {\n rel: 'preload',\n as: 'script',\n };\n jsAssetsWithoutEntry.forEach((jsUrl) => {\n results.push(\n waitForLinkPreload({\n host,\n remoteInfo,\n url: jsUrl,\n attrs: defaultAttrs,\n context: createResourceContext(baseContext, 'js'),\n }),\n );\n });\n } else {\n const defaultAttrs = {\n fetchpriority: 'high',\n type: remoteInfo?.type === 'module' ? 'module' : 'text/javascript',\n };\n jsAssetsWithoutEntry.forEach((jsUrl) => {\n results.push(\n waitForScriptPreload({\n host,\n remoteInfo,\n url: jsUrl,\n attrs: defaultAttrs,\n context: createResourceContext(baseContext, 'js'),\n }),\n );\n });\n }\n }\n\n return Promise.all(results);\n}\n"],"mappings":"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"}
|