@module-federation/data-prefetch 0.0.0-next-20240909062831 → 0.0.0-next-20240911025149
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/CHANGELOG.md +3 -3
- package/README.md +1 -1
- package/dist/cli/index.d.ts +10 -2
- package/dist/cli/index.js +54 -2
- package/dist/esm/chunk-EZUCZHGV.js +11 -0
- package/dist/esm/{chunk-H3DTWHY4.js → chunk-YXTPJG2M.js} +65 -1
- package/dist/esm/cli/babel.js +2 -0
- package/dist/esm/cli/index.js +57 -2
- package/dist/esm/index.js +2 -1
- package/dist/esm/plugin.js +2 -1
- package/dist/esm/react/index.js +1 -0
- package/dist/esm/shared/index.js +2 -0
- package/dist/esm/universal/index.js +1 -0
- package/dist/index.js +65 -1
- package/dist/plugin.js +65 -1
- package/package.json +3 -3
- package/src/cli/babel.ts +1 -0
- package/src/cli/index.ts +67 -0
- package/src/plugin.ts +77 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
@module-federation/data-prefetch
|
|
2
2
|
|
|
3
|
-
## 0.0.0-next-
|
|
3
|
+
## 0.0.0-next-20240911025149
|
|
4
4
|
|
|
5
5
|
### Patch Changes
|
|
6
6
|
|
|
7
7
|
- 3ddab21: feat(@module-federation/data-prefetch): support data prefetch in Module Federation
|
|
8
|
-
- @module-federation/runtime@0.0.0-next-
|
|
9
|
-
- @module-federation/sdk@0.0.0-next-
|
|
8
|
+
- @module-federation/runtime@0.0.0-next-20240911025149
|
|
9
|
+
- @module-federation/sdk@0.0.0-next-20240911025149
|
package/README.md
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Module Federation Data Prefetch
|
|
1
|
+
Module Federation Data Prefetch(https://module-federation.io/zh/guide/performance/prefetch.html)
|
package/dist/cli/index.d.ts
CHANGED
|
@@ -1,11 +1,19 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as webpack from 'webpack';
|
|
2
2
|
import { WebpackPluginInstance, Compiler } from 'webpack';
|
|
3
|
+
import { moduleFederationPlugin } from '@module-federation/sdk';
|
|
3
4
|
|
|
5
|
+
declare const RuntimeGlobals: typeof webpack.RuntimeGlobals;
|
|
6
|
+
declare function getFederationGlobalScope(runtimeGlobals: typeof RuntimeGlobals): string;
|
|
4
7
|
declare class PrefetchPlugin implements WebpackPluginInstance {
|
|
5
8
|
options: moduleFederationPlugin.ModuleFederationPluginOptions;
|
|
6
9
|
private _reWriteExports;
|
|
7
10
|
constructor(options: moduleFederationPlugin.ModuleFederationPluginOptions);
|
|
8
11
|
apply(compiler: Compiler): void;
|
|
12
|
+
static addRuntime(compiler: Compiler, options: {
|
|
13
|
+
name: string;
|
|
14
|
+
}): string;
|
|
15
|
+
static setRemoteIdentifier(): string;
|
|
16
|
+
static removeRemoteIdentifier(): string;
|
|
9
17
|
}
|
|
10
18
|
|
|
11
|
-
export { PrefetchPlugin };
|
|
19
|
+
export { PrefetchPlugin, getFederationGlobalScope };
|
package/dist/cli/index.js
CHANGED
|
@@ -26,12 +26,14 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
26
26
|
// src/cli/index.ts
|
|
27
27
|
var cli_exports = {};
|
|
28
28
|
__export(cli_exports, {
|
|
29
|
-
PrefetchPlugin: () => PrefetchPlugin
|
|
29
|
+
PrefetchPlugin: () => PrefetchPlugin,
|
|
30
|
+
getFederationGlobalScope: () => getFederationGlobalScope
|
|
30
31
|
});
|
|
31
32
|
module.exports = __toCommonJS(cli_exports);
|
|
32
33
|
var import_path2 = __toESM(require("path"));
|
|
33
34
|
var import_fs_extra2 = __toESM(require("fs-extra"));
|
|
34
35
|
var import_sdk2 = require("@module-federation/sdk");
|
|
36
|
+
var import_normalize_webpack_path = require("@module-federation/sdk/normalize-webpack-path");
|
|
35
37
|
|
|
36
38
|
// src/common/constant.ts
|
|
37
39
|
var TEMP_DIR = ".mf";
|
|
@@ -65,6 +67,10 @@ var import_sdk = require("@module-federation/sdk");
|
|
|
65
67
|
var getPrefetchId = (id) => (0, import_sdk.encodeName)(`${id}/${import_sdk.MFPrefetchCommon.identifier}`);
|
|
66
68
|
|
|
67
69
|
// src/cli/index.ts
|
|
70
|
+
var { RuntimeGlobals, Template } = require((0, import_normalize_webpack_path.normalizeWebpackPath)("webpack"));
|
|
71
|
+
function getFederationGlobalScope(runtimeGlobals) {
|
|
72
|
+
return `${runtimeGlobals.require || "__webpack_require__"}.federation`;
|
|
73
|
+
}
|
|
68
74
|
var PrefetchPlugin = class {
|
|
69
75
|
constructor(options) {
|
|
70
76
|
this.options = options;
|
|
@@ -142,8 +148,54 @@ var PrefetchPlugin = class {
|
|
|
142
148
|
FederationDataPrefetch: JSON.stringify(asyncEntryPath)
|
|
143
149
|
}).apply(compiler);
|
|
144
150
|
}
|
|
151
|
+
static addRuntime(compiler, options) {
|
|
152
|
+
const encodedName = (0, import_sdk2.encodeName)(options.name);
|
|
153
|
+
if (!compiler.options.context) {
|
|
154
|
+
throw new Error("compiler.options.context is not defined");
|
|
155
|
+
}
|
|
156
|
+
const prefetchEntry = import_path2.default.resolve(
|
|
157
|
+
compiler.options.context,
|
|
158
|
+
`node_modules/.mf/${encodedName}/bootstrap.js`
|
|
159
|
+
);
|
|
160
|
+
const federationGlobal = getFederationGlobalScope(
|
|
161
|
+
RuntimeGlobals || {}
|
|
162
|
+
);
|
|
163
|
+
return Template.asString([
|
|
164
|
+
import_fs_extra2.default.existsSync(prefetchEntry) ? Template.indent([
|
|
165
|
+
"function injectPrefetch() {",
|
|
166
|
+
`globalThis.__FEDERATION__ = globalThis.__FEDERATION__ || {};`,
|
|
167
|
+
`globalThis.__FEDERATION__['${import_sdk2.MFPrefetchCommon.globalKey}'] = globalThis.__FEDERATION__['${import_sdk2.MFPrefetchCommon.globalKey}'] || {`,
|
|
168
|
+
`entryLoading: {},`,
|
|
169
|
+
`instance: new Map(),`,
|
|
170
|
+
`__PREFETCH_EXPORTS__: {},`,
|
|
171
|
+
`};`,
|
|
172
|
+
`globalThis.__FEDERATION__['${import_sdk2.MFPrefetchCommon.globalKey}']['${import_sdk2.MFPrefetchCommon.exportsKey}'] = globalThis.__FEDERATION__['${import_sdk2.MFPrefetchCommon.globalKey}']['${import_sdk2.MFPrefetchCommon.exportsKey}'] || {};`,
|
|
173
|
+
`globalThis.__FEDERATION__['${import_sdk2.MFPrefetchCommon.globalKey}']['${import_sdk2.MFPrefetchCommon.exportsKey}']['${options.name}'] = import('${prefetchEntry}');`,
|
|
174
|
+
"}",
|
|
175
|
+
`${federationGlobal}.prefetch = injectPrefetch`
|
|
176
|
+
]) : "",
|
|
177
|
+
Template.indent([
|
|
178
|
+
`if(!globalThis.isMFRemote && ${federationGlobal}.prefetch){`,
|
|
179
|
+
`${federationGlobal}.prefetch()`,
|
|
180
|
+
"}"
|
|
181
|
+
])
|
|
182
|
+
]);
|
|
183
|
+
}
|
|
184
|
+
static setRemoteIdentifier() {
|
|
185
|
+
const federationGlobal = getFederationGlobalScope(
|
|
186
|
+
RuntimeGlobals || {}
|
|
187
|
+
);
|
|
188
|
+
return Template.indent([`${federationGlobal}.isMFRemote = true;`]);
|
|
189
|
+
}
|
|
190
|
+
static removeRemoteIdentifier() {
|
|
191
|
+
const federationGlobal = getFederationGlobalScope(
|
|
192
|
+
RuntimeGlobals || {}
|
|
193
|
+
);
|
|
194
|
+
return Template.indent([`${federationGlobal}.isMFRemote = false;`]);
|
|
195
|
+
}
|
|
145
196
|
};
|
|
146
197
|
// Annotate the CommonJS export names for ESM import in node:
|
|
147
198
|
0 && (module.exports = {
|
|
148
|
-
PrefetchPlugin
|
|
199
|
+
PrefetchPlugin,
|
|
200
|
+
getFederationGlobalScope
|
|
149
201
|
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined")
|
|
5
|
+
return require.apply(this, arguments);
|
|
6
|
+
throw new Error('Dynamic require of "' + x + '" is not supported');
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
export {
|
|
10
|
+
__require
|
|
11
|
+
};
|
|
@@ -50,7 +50,71 @@ var prefetchPlugin = () => ({
|
|
|
50
50
|
}
|
|
51
51
|
return Promise.resolve().then(() => {
|
|
52
52
|
const exports = instance.getExposeExports(id);
|
|
53
|
-
logger_default.info(
|
|
53
|
+
logger_default.info(
|
|
54
|
+
`1. Start Prefetch initContainer: ${id} - ${performance.now()}`
|
|
55
|
+
);
|
|
56
|
+
const result = Object.keys(exports).map((k) => {
|
|
57
|
+
const value = instance.prefetch({
|
|
58
|
+
id,
|
|
59
|
+
functionId: k
|
|
60
|
+
});
|
|
61
|
+
const functionId = k;
|
|
62
|
+
return {
|
|
63
|
+
value,
|
|
64
|
+
functionId
|
|
65
|
+
};
|
|
66
|
+
});
|
|
67
|
+
return result;
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
loadingArray.push({
|
|
71
|
+
id,
|
|
72
|
+
promise
|
|
73
|
+
});
|
|
74
|
+
return options;
|
|
75
|
+
},
|
|
76
|
+
afterResolve(options) {
|
|
77
|
+
const { remoteSnapshot, remoteInfo, id, origin } = options;
|
|
78
|
+
const snapshot = remoteSnapshot;
|
|
79
|
+
const { name } = remoteInfo;
|
|
80
|
+
const prefetchOptions = {
|
|
81
|
+
name,
|
|
82
|
+
remote: remoteInfo,
|
|
83
|
+
origin,
|
|
84
|
+
remoteSnapshot: snapshot
|
|
85
|
+
};
|
|
86
|
+
const signal = getSignalFromManifest(snapshot);
|
|
87
|
+
if (!signal) {
|
|
88
|
+
return options;
|
|
89
|
+
}
|
|
90
|
+
const inited = loadingArray.some((info) => info.id === id);
|
|
91
|
+
if (!inited) {
|
|
92
|
+
return options;
|
|
93
|
+
}
|
|
94
|
+
if (sharedFlag !== strategy) {
|
|
95
|
+
throw new Error(
|
|
96
|
+
`[Module Federation Data Prefetch]: If you want to use data prefetch, the shared strategy must be 'loaded-first'`
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
const instance = MFDataPrefetch.getInstance(name) || new MFDataPrefetch(prefetchOptions);
|
|
100
|
+
let prefetchUrl;
|
|
101
|
+
if (snapshot.prefetchEntry) {
|
|
102
|
+
prefetchUrl = getResourceUrl(snapshot, snapshot.prefetchEntry);
|
|
103
|
+
}
|
|
104
|
+
const index = loadingArray.findIndex((loading) => loading.id === id);
|
|
105
|
+
if (index !== -1) {
|
|
106
|
+
loadingArray.splice(index, 1);
|
|
107
|
+
}
|
|
108
|
+
const promise = instance.loadEntry(prefetchUrl).then(async () => {
|
|
109
|
+
const projectExports = instance.getProjectExports();
|
|
110
|
+
if (projectExports instanceof Promise) {
|
|
111
|
+
await projectExports;
|
|
112
|
+
}
|
|
113
|
+
return Promise.resolve().then(() => {
|
|
114
|
+
const exports = instance.getExposeExports(id);
|
|
115
|
+
logger_default.info(
|
|
116
|
+
`1. Start Prefetch afterResolve: ${id} - ${performance.now()}`
|
|
117
|
+
);
|
|
54
118
|
const result = Object.keys(exports).map((k) => {
|
|
55
119
|
const value = instance.prefetch({
|
|
56
120
|
id,
|
package/dist/esm/cli/babel.js
CHANGED
package/dist/esm/cli/index.js
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getPrefetchId
|
|
3
3
|
} from "../chunk-VWDP6NMM.js";
|
|
4
|
+
import {
|
|
5
|
+
__require
|
|
6
|
+
} from "../chunk-EZUCZHGV.js";
|
|
4
7
|
|
|
5
8
|
// src/cli/index.ts
|
|
6
9
|
import path2 from "path";
|
|
7
10
|
import fs2 from "fs-extra";
|
|
8
11
|
import {
|
|
9
|
-
encodeName
|
|
12
|
+
encodeName,
|
|
13
|
+
MFPrefetchCommon
|
|
10
14
|
} from "@module-federation/sdk";
|
|
15
|
+
import { normalizeWebpackPath } from "@module-federation/sdk/normalize-webpack-path";
|
|
11
16
|
|
|
12
17
|
// src/common/constant.ts
|
|
13
18
|
var TEMP_DIR = ".mf";
|
|
@@ -37,6 +42,10 @@ var fixPrefetchPath = (exposePath) => {
|
|
|
37
42
|
};
|
|
38
43
|
|
|
39
44
|
// src/cli/index.ts
|
|
45
|
+
var { RuntimeGlobals, Template } = __require(normalizeWebpackPath("webpack"));
|
|
46
|
+
function getFederationGlobalScope(runtimeGlobals) {
|
|
47
|
+
return `${runtimeGlobals.require || "__webpack_require__"}.federation`;
|
|
48
|
+
}
|
|
40
49
|
var PrefetchPlugin = class {
|
|
41
50
|
constructor(options) {
|
|
42
51
|
this.options = options;
|
|
@@ -114,7 +123,53 @@ var PrefetchPlugin = class {
|
|
|
114
123
|
FederationDataPrefetch: JSON.stringify(asyncEntryPath)
|
|
115
124
|
}).apply(compiler);
|
|
116
125
|
}
|
|
126
|
+
static addRuntime(compiler, options) {
|
|
127
|
+
const encodedName = encodeName(options.name);
|
|
128
|
+
if (!compiler.options.context) {
|
|
129
|
+
throw new Error("compiler.options.context is not defined");
|
|
130
|
+
}
|
|
131
|
+
const prefetchEntry = path2.resolve(
|
|
132
|
+
compiler.options.context,
|
|
133
|
+
`node_modules/.mf/${encodedName}/bootstrap.js`
|
|
134
|
+
);
|
|
135
|
+
const federationGlobal = getFederationGlobalScope(
|
|
136
|
+
RuntimeGlobals || {}
|
|
137
|
+
);
|
|
138
|
+
return Template.asString([
|
|
139
|
+
fs2.existsSync(prefetchEntry) ? Template.indent([
|
|
140
|
+
"function injectPrefetch() {",
|
|
141
|
+
`globalThis.__FEDERATION__ = globalThis.__FEDERATION__ || {};`,
|
|
142
|
+
`globalThis.__FEDERATION__['${MFPrefetchCommon.globalKey}'] = globalThis.__FEDERATION__['${MFPrefetchCommon.globalKey}'] || {`,
|
|
143
|
+
`entryLoading: {},`,
|
|
144
|
+
`instance: new Map(),`,
|
|
145
|
+
`__PREFETCH_EXPORTS__: {},`,
|
|
146
|
+
`};`,
|
|
147
|
+
`globalThis.__FEDERATION__['${MFPrefetchCommon.globalKey}']['${MFPrefetchCommon.exportsKey}'] = globalThis.__FEDERATION__['${MFPrefetchCommon.globalKey}']['${MFPrefetchCommon.exportsKey}'] || {};`,
|
|
148
|
+
`globalThis.__FEDERATION__['${MFPrefetchCommon.globalKey}']['${MFPrefetchCommon.exportsKey}']['${options.name}'] = import('${prefetchEntry}');`,
|
|
149
|
+
"}",
|
|
150
|
+
`${federationGlobal}.prefetch = injectPrefetch`
|
|
151
|
+
]) : "",
|
|
152
|
+
Template.indent([
|
|
153
|
+
`if(!globalThis.isMFRemote && ${federationGlobal}.prefetch){`,
|
|
154
|
+
`${federationGlobal}.prefetch()`,
|
|
155
|
+
"}"
|
|
156
|
+
])
|
|
157
|
+
]);
|
|
158
|
+
}
|
|
159
|
+
static setRemoteIdentifier() {
|
|
160
|
+
const federationGlobal = getFederationGlobalScope(
|
|
161
|
+
RuntimeGlobals || {}
|
|
162
|
+
);
|
|
163
|
+
return Template.indent([`${federationGlobal}.isMFRemote = true;`]);
|
|
164
|
+
}
|
|
165
|
+
static removeRemoteIdentifier() {
|
|
166
|
+
const federationGlobal = getFederationGlobalScope(
|
|
167
|
+
RuntimeGlobals || {}
|
|
168
|
+
);
|
|
169
|
+
return Template.indent([`${federationGlobal}.isMFRemote = false;`]);
|
|
170
|
+
}
|
|
117
171
|
};
|
|
118
172
|
export {
|
|
119
|
-
PrefetchPlugin
|
|
173
|
+
PrefetchPlugin,
|
|
174
|
+
getFederationGlobalScope
|
|
120
175
|
};
|
package/dist/esm/index.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
prefetchPlugin
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-YXTPJG2M.js";
|
|
4
4
|
import "./chunk-TTJJJ2WZ.js";
|
|
5
5
|
import {
|
|
6
6
|
MFDataPrefetch
|
|
7
7
|
} from "./chunk-57ZXBP7D.js";
|
|
8
8
|
import "./chunk-VWDP6NMM.js";
|
|
9
|
+
import "./chunk-EZUCZHGV.js";
|
|
9
10
|
export {
|
|
10
11
|
MFDataPrefetch,
|
|
11
12
|
prefetchPlugin
|
package/dist/esm/plugin.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
plugin_default,
|
|
3
3
|
prefetchPlugin
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-YXTPJG2M.js";
|
|
5
5
|
import "./chunk-TTJJJ2WZ.js";
|
|
6
6
|
import "./chunk-57ZXBP7D.js";
|
|
7
7
|
import "./chunk-VWDP6NMM.js";
|
|
8
|
+
import "./chunk-EZUCZHGV.js";
|
|
8
9
|
export {
|
|
9
10
|
plugin_default as default,
|
|
10
11
|
prefetchPlugin
|
package/dist/esm/react/index.js
CHANGED
package/dist/esm/shared/index.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -234,7 +234,71 @@ var prefetchPlugin = () => ({
|
|
|
234
234
|
}
|
|
235
235
|
return Promise.resolve().then(() => {
|
|
236
236
|
const exports = instance.getExposeExports(id);
|
|
237
|
-
logger_default.info(
|
|
237
|
+
logger_default.info(
|
|
238
|
+
`1. Start Prefetch initContainer: ${id} - ${performance.now()}`
|
|
239
|
+
);
|
|
240
|
+
const result = Object.keys(exports).map((k) => {
|
|
241
|
+
const value = instance.prefetch({
|
|
242
|
+
id,
|
|
243
|
+
functionId: k
|
|
244
|
+
});
|
|
245
|
+
const functionId = k;
|
|
246
|
+
return {
|
|
247
|
+
value,
|
|
248
|
+
functionId
|
|
249
|
+
};
|
|
250
|
+
});
|
|
251
|
+
return result;
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
loadingArray.push({
|
|
255
|
+
id,
|
|
256
|
+
promise
|
|
257
|
+
});
|
|
258
|
+
return options;
|
|
259
|
+
},
|
|
260
|
+
afterResolve(options) {
|
|
261
|
+
const { remoteSnapshot, remoteInfo, id, origin } = options;
|
|
262
|
+
const snapshot = remoteSnapshot;
|
|
263
|
+
const { name } = remoteInfo;
|
|
264
|
+
const prefetchOptions = {
|
|
265
|
+
name,
|
|
266
|
+
remote: remoteInfo,
|
|
267
|
+
origin,
|
|
268
|
+
remoteSnapshot: snapshot
|
|
269
|
+
};
|
|
270
|
+
const signal = getSignalFromManifest(snapshot);
|
|
271
|
+
if (!signal) {
|
|
272
|
+
return options;
|
|
273
|
+
}
|
|
274
|
+
const inited = loadingArray.some((info) => info.id === id);
|
|
275
|
+
if (!inited) {
|
|
276
|
+
return options;
|
|
277
|
+
}
|
|
278
|
+
if (sharedFlag !== strategy) {
|
|
279
|
+
throw new Error(
|
|
280
|
+
`[Module Federation Data Prefetch]: If you want to use data prefetch, the shared strategy must be 'loaded-first'`
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
const instance = MFDataPrefetch.getInstance(name) || new MFDataPrefetch(prefetchOptions);
|
|
284
|
+
let prefetchUrl;
|
|
285
|
+
if (snapshot.prefetchEntry) {
|
|
286
|
+
prefetchUrl = (0, import_sdk4.getResourceUrl)(snapshot, snapshot.prefetchEntry);
|
|
287
|
+
}
|
|
288
|
+
const index = loadingArray.findIndex((loading) => loading.id === id);
|
|
289
|
+
if (index !== -1) {
|
|
290
|
+
loadingArray.splice(index, 1);
|
|
291
|
+
}
|
|
292
|
+
const promise = instance.loadEntry(prefetchUrl).then(async () => {
|
|
293
|
+
const projectExports = instance.getProjectExports();
|
|
294
|
+
if (projectExports instanceof Promise) {
|
|
295
|
+
await projectExports;
|
|
296
|
+
}
|
|
297
|
+
return Promise.resolve().then(() => {
|
|
298
|
+
const exports = instance.getExposeExports(id);
|
|
299
|
+
logger_default.info(
|
|
300
|
+
`1. Start Prefetch afterResolve: ${id} - ${performance.now()}`
|
|
301
|
+
);
|
|
238
302
|
const result = Object.keys(exports).map((k) => {
|
|
239
303
|
const value = instance.prefetch({
|
|
240
304
|
id,
|
package/dist/plugin.js
CHANGED
|
@@ -230,7 +230,71 @@ var prefetchPlugin = () => ({
|
|
|
230
230
|
}
|
|
231
231
|
return Promise.resolve().then(() => {
|
|
232
232
|
const exports = instance.getExposeExports(id);
|
|
233
|
-
logger_default.info(
|
|
233
|
+
logger_default.info(
|
|
234
|
+
`1. Start Prefetch initContainer: ${id} - ${performance.now()}`
|
|
235
|
+
);
|
|
236
|
+
const result = Object.keys(exports).map((k) => {
|
|
237
|
+
const value = instance.prefetch({
|
|
238
|
+
id,
|
|
239
|
+
functionId: k
|
|
240
|
+
});
|
|
241
|
+
const functionId = k;
|
|
242
|
+
return {
|
|
243
|
+
value,
|
|
244
|
+
functionId
|
|
245
|
+
};
|
|
246
|
+
});
|
|
247
|
+
return result;
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
loadingArray.push({
|
|
251
|
+
id,
|
|
252
|
+
promise
|
|
253
|
+
});
|
|
254
|
+
return options;
|
|
255
|
+
},
|
|
256
|
+
afterResolve(options) {
|
|
257
|
+
const { remoteSnapshot, remoteInfo, id, origin } = options;
|
|
258
|
+
const snapshot = remoteSnapshot;
|
|
259
|
+
const { name } = remoteInfo;
|
|
260
|
+
const prefetchOptions = {
|
|
261
|
+
name,
|
|
262
|
+
remote: remoteInfo,
|
|
263
|
+
origin,
|
|
264
|
+
remoteSnapshot: snapshot
|
|
265
|
+
};
|
|
266
|
+
const signal = getSignalFromManifest(snapshot);
|
|
267
|
+
if (!signal) {
|
|
268
|
+
return options;
|
|
269
|
+
}
|
|
270
|
+
const inited = loadingArray.some((info) => info.id === id);
|
|
271
|
+
if (!inited) {
|
|
272
|
+
return options;
|
|
273
|
+
}
|
|
274
|
+
if (sharedFlag !== strategy) {
|
|
275
|
+
throw new Error(
|
|
276
|
+
`[Module Federation Data Prefetch]: If you want to use data prefetch, the shared strategy must be 'loaded-first'`
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
const instance = MFDataPrefetch.getInstance(name) || new MFDataPrefetch(prefetchOptions);
|
|
280
|
+
let prefetchUrl;
|
|
281
|
+
if (snapshot.prefetchEntry) {
|
|
282
|
+
prefetchUrl = (0, import_sdk4.getResourceUrl)(snapshot, snapshot.prefetchEntry);
|
|
283
|
+
}
|
|
284
|
+
const index = loadingArray.findIndex((loading) => loading.id === id);
|
|
285
|
+
if (index !== -1) {
|
|
286
|
+
loadingArray.splice(index, 1);
|
|
287
|
+
}
|
|
288
|
+
const promise = instance.loadEntry(prefetchUrl).then(async () => {
|
|
289
|
+
const projectExports = instance.getProjectExports();
|
|
290
|
+
if (projectExports instanceof Promise) {
|
|
291
|
+
await projectExports;
|
|
292
|
+
}
|
|
293
|
+
return Promise.resolve().then(() => {
|
|
294
|
+
const exports = instance.getExposeExports(id);
|
|
295
|
+
logger_default.info(
|
|
296
|
+
`1. Start Prefetch afterResolve: ${id} - ${performance.now()}`
|
|
297
|
+
);
|
|
234
298
|
const result = Object.keys(exports).map((k) => {
|
|
235
299
|
const value = instance.prefetch({
|
|
236
300
|
id,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@module-federation/data-prefetch",
|
|
3
3
|
"description": "Module Federation Data Prefetch",
|
|
4
|
-
"version": "0.0.0-next-
|
|
4
|
+
"version": "0.0.0-next-20240911025149",
|
|
5
5
|
"author": "nieyan <nyqykk@foxmail.com>",
|
|
6
6
|
"homepage": "https://github.com/module-federation/core",
|
|
7
7
|
"license": "MIT",
|
|
@@ -85,8 +85,8 @@
|
|
|
85
85
|
},
|
|
86
86
|
"dependencies": {
|
|
87
87
|
"fs-extra": "9.1.0",
|
|
88
|
-
"@module-federation/sdk": "0.0.0-next-
|
|
89
|
-
"@module-federation/runtime": "0.0.0-next-
|
|
88
|
+
"@module-federation/sdk": "0.0.0-next-20240911025149",
|
|
89
|
+
"@module-federation/runtime": "0.0.0-next-20240911025149"
|
|
90
90
|
},
|
|
91
91
|
"scripts": {
|
|
92
92
|
"dev": "cross-env WATCH=true tsup",
|
package/src/cli/babel.ts
CHANGED
package/src/cli/index.ts
CHANGED
|
@@ -6,12 +6,23 @@ import {
|
|
|
6
6
|
moduleFederationPlugin,
|
|
7
7
|
MFPrefetchCommon,
|
|
8
8
|
} from '@module-federation/sdk';
|
|
9
|
+
import { normalizeWebpackPath } from '@module-federation/sdk/normalize-webpack-path';
|
|
9
10
|
import type { Compiler, WebpackPluginInstance } from 'webpack';
|
|
10
11
|
|
|
11
12
|
import { TEMP_DIR } from '../common/constant';
|
|
12
13
|
import { fileExistsWithCaseSync, fixPrefetchPath } from '../common/node-utils';
|
|
13
14
|
import { getPrefetchId } from '../common/runtime-utils';
|
|
14
15
|
|
|
16
|
+
const { RuntimeGlobals, Template } = require(
|
|
17
|
+
normalizeWebpackPath('webpack'),
|
|
18
|
+
) as typeof import('webpack');
|
|
19
|
+
|
|
20
|
+
export function getFederationGlobalScope(
|
|
21
|
+
runtimeGlobals: typeof RuntimeGlobals,
|
|
22
|
+
): string {
|
|
23
|
+
return `${runtimeGlobals.require || '__webpack_require__'}.federation`;
|
|
24
|
+
}
|
|
25
|
+
|
|
15
26
|
export class PrefetchPlugin implements WebpackPluginInstance {
|
|
16
27
|
public options: moduleFederationPlugin.ModuleFederationPluginOptions;
|
|
17
28
|
private _reWriteExports: string;
|
|
@@ -97,4 +108,60 @@ export class PrefetchPlugin implements WebpackPluginInstance {
|
|
|
97
108
|
FederationDataPrefetch: JSON.stringify(asyncEntryPath),
|
|
98
109
|
}).apply(compiler);
|
|
99
110
|
}
|
|
111
|
+
|
|
112
|
+
static addRuntime(
|
|
113
|
+
compiler: Compiler,
|
|
114
|
+
options: {
|
|
115
|
+
name: string;
|
|
116
|
+
},
|
|
117
|
+
) {
|
|
118
|
+
const encodedName = encodeName(options.name as string);
|
|
119
|
+
if (!compiler.options.context) {
|
|
120
|
+
throw new Error('compiler.options.context is not defined');
|
|
121
|
+
}
|
|
122
|
+
const prefetchEntry = path.resolve(
|
|
123
|
+
compiler.options.context,
|
|
124
|
+
`node_modules/.mf/${encodedName}/bootstrap.js`,
|
|
125
|
+
);
|
|
126
|
+
const federationGlobal = getFederationGlobalScope(
|
|
127
|
+
RuntimeGlobals || ({} as typeof RuntimeGlobals),
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
return Template.asString([
|
|
131
|
+
fs.existsSync(prefetchEntry)
|
|
132
|
+
? Template.indent([
|
|
133
|
+
'function injectPrefetch() {',
|
|
134
|
+
`globalThis.__FEDERATION__ = globalThis.__FEDERATION__ || {};`,
|
|
135
|
+
`globalThis.__FEDERATION__['${MFPrefetchCommon.globalKey}'] = globalThis.__FEDERATION__['${MFPrefetchCommon.globalKey}'] || {`,
|
|
136
|
+
`entryLoading: {},`,
|
|
137
|
+
`instance: new Map(),`,
|
|
138
|
+
`__PREFETCH_EXPORTS__: {},`,
|
|
139
|
+
`};`,
|
|
140
|
+
`globalThis.__FEDERATION__['${MFPrefetchCommon.globalKey}']['${MFPrefetchCommon.exportsKey}'] = globalThis.__FEDERATION__['${MFPrefetchCommon.globalKey}']['${MFPrefetchCommon.exportsKey}'] || {};`,
|
|
141
|
+
`globalThis.__FEDERATION__['${MFPrefetchCommon.globalKey}']['${MFPrefetchCommon.exportsKey}']['${options.name}'] = import('${prefetchEntry}');`,
|
|
142
|
+
'}',
|
|
143
|
+
`${federationGlobal}.prefetch = injectPrefetch`,
|
|
144
|
+
])
|
|
145
|
+
: '',
|
|
146
|
+
Template.indent([
|
|
147
|
+
`if(!globalThis.isMFRemote && ${federationGlobal}.prefetch){`,
|
|
148
|
+
`${federationGlobal}.prefetch()`,
|
|
149
|
+
'}',
|
|
150
|
+
]),
|
|
151
|
+
]);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
static setRemoteIdentifier() {
|
|
155
|
+
const federationGlobal = getFederationGlobalScope(
|
|
156
|
+
RuntimeGlobals || ({} as typeof RuntimeGlobals),
|
|
157
|
+
);
|
|
158
|
+
return Template.indent([`${federationGlobal}.isMFRemote = true;`]);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
static removeRemoteIdentifier() {
|
|
162
|
+
const federationGlobal = getFederationGlobalScope(
|
|
163
|
+
RuntimeGlobals || ({} as typeof RuntimeGlobals),
|
|
164
|
+
);
|
|
165
|
+
return Template.indent([`${federationGlobal}.isMFRemote = false;`]);
|
|
166
|
+
}
|
|
100
167
|
}
|
package/src/plugin.ts
CHANGED
|
@@ -55,7 +55,6 @@ export const prefetchPlugin = (): FederationRuntimePlugin => ({
|
|
|
55
55
|
if (exist) {
|
|
56
56
|
return options;
|
|
57
57
|
}
|
|
58
|
-
// @ts-ignore
|
|
59
58
|
const promise = instance.loadEntry(prefetchUrl).then(async () => {
|
|
60
59
|
const projectExports = instance!.getProjectExports();
|
|
61
60
|
if (projectExports instanceof Promise) {
|
|
@@ -63,7 +62,9 @@ export const prefetchPlugin = (): FederationRuntimePlugin => ({
|
|
|
63
62
|
}
|
|
64
63
|
return Promise.resolve().then(() => {
|
|
65
64
|
const exports = instance!.getExposeExports(id);
|
|
66
|
-
logger.info(
|
|
65
|
+
logger.info(
|
|
66
|
+
`1. Start Prefetch initContainer: ${id} - ${performance.now()}`,
|
|
67
|
+
);
|
|
67
68
|
const result = Object.keys(exports).map((k) => {
|
|
68
69
|
const value = instance!.prefetch({
|
|
69
70
|
id,
|
|
@@ -87,6 +88,80 @@ export const prefetchPlugin = (): FederationRuntimePlugin => ({
|
|
|
87
88
|
return options;
|
|
88
89
|
},
|
|
89
90
|
|
|
91
|
+
afterResolve(options) {
|
|
92
|
+
const { remoteSnapshot, remoteInfo, id, origin } = options;
|
|
93
|
+
const snapshot = remoteSnapshot as ModuleInfo;
|
|
94
|
+
const { name } = remoteInfo;
|
|
95
|
+
|
|
96
|
+
const prefetchOptions = {
|
|
97
|
+
name,
|
|
98
|
+
remote: remoteInfo,
|
|
99
|
+
origin,
|
|
100
|
+
remoteSnapshot: snapshot,
|
|
101
|
+
};
|
|
102
|
+
const signal = getSignalFromManifest(snapshot);
|
|
103
|
+
if (!signal) {
|
|
104
|
+
return options;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const inited = loadingArray.some((info) => info.id === id);
|
|
108
|
+
if (!inited) {
|
|
109
|
+
return options;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (sharedFlag !== strategy) {
|
|
113
|
+
throw new Error(
|
|
114
|
+
`[Module Federation Data Prefetch]: If you want to use data prefetch, the shared strategy must be 'loaded-first'`,
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const instance =
|
|
119
|
+
MFDataPrefetch.getInstance(name) || new MFDataPrefetch(prefetchOptions);
|
|
120
|
+
|
|
121
|
+
let prefetchUrl;
|
|
122
|
+
// @ts-expect-error
|
|
123
|
+
if (snapshot.prefetchEntry) {
|
|
124
|
+
// @ts-expect-error
|
|
125
|
+
prefetchUrl = getResourceUrl(snapshot, snapshot.prefetchEntry as string);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const index = loadingArray.findIndex((loading) => loading.id === id);
|
|
129
|
+
// clear cache
|
|
130
|
+
if (index !== -1) {
|
|
131
|
+
loadingArray.splice(index, 1);
|
|
132
|
+
}
|
|
133
|
+
const promise = instance.loadEntry(prefetchUrl).then(async () => {
|
|
134
|
+
const projectExports = instance!.getProjectExports();
|
|
135
|
+
if (projectExports instanceof Promise) {
|
|
136
|
+
await projectExports;
|
|
137
|
+
}
|
|
138
|
+
return Promise.resolve().then(() => {
|
|
139
|
+
const exports = instance!.getExposeExports(id);
|
|
140
|
+
logger.info(
|
|
141
|
+
`1. Start Prefetch afterResolve: ${id} - ${performance.now()}`,
|
|
142
|
+
);
|
|
143
|
+
const result = Object.keys(exports).map((k) => {
|
|
144
|
+
const value = instance!.prefetch({
|
|
145
|
+
id,
|
|
146
|
+
functionId: k,
|
|
147
|
+
});
|
|
148
|
+
const functionId = k;
|
|
149
|
+
|
|
150
|
+
return {
|
|
151
|
+
value,
|
|
152
|
+
functionId,
|
|
153
|
+
};
|
|
154
|
+
});
|
|
155
|
+
return result;
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
loadingArray.push({
|
|
160
|
+
id,
|
|
161
|
+
promise,
|
|
162
|
+
});
|
|
163
|
+
return options;
|
|
164
|
+
},
|
|
90
165
|
async onLoad(options) {
|
|
91
166
|
const { remote, id } = options;
|
|
92
167
|
const { name } = remote;
|