@module-federation/runtime 0.0.6 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +513 -124
- package/dist/helpers.cjs.js +2 -1
- package/dist/helpers.esm.js +3 -2
- package/dist/index.cjs.js +208 -104
- package/dist/index.esm.js +207 -106
- package/dist/package.json +3 -3
- package/dist/share.cjs.js +147 -111
- package/dist/share.esm.js +147 -111
- package/dist/src/core.d.ts +39 -7
- package/dist/src/global.d.ts +3 -6
- package/dist/src/helpers.d.ts +4 -3
- package/dist/src/index.d.ts +3 -1
- package/dist/src/module/index.d.ts +4 -10
- package/dist/src/type/config.d.ts +8 -2
- package/dist/src/type/plugin.d.ts +1 -1
- package/dist/src/utils/plugin.d.ts +1 -1
- package/dist/src/utils/share.d.ts +12 -3
- package/dist/types.cjs.d.ts +1 -0
- package/package.json +4 -4
- package/dist/type.cjs.d.ts +0 -1
- /package/dist/{type.cjs.js → types.cjs.js} +0 -0
- /package/dist/{type.esm.js → types.esm.js} +0 -0
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
- Only consume part of the export of the remote module and will not fully download the remote module
|
|
5
5
|
- The runtime calling process can be extended through the module-runtime plug-in mechanism
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## API
|
|
8
8
|
|
|
9
9
|
```javascript
|
|
10
10
|
// Can load modules using only the runtime SDK without relying on build plugins
|
|
@@ -16,18 +16,14 @@ init({
|
|
|
16
16
|
remotes: [
|
|
17
17
|
{
|
|
18
18
|
name: "@demo/app2",
|
|
19
|
-
entry: "http://localhost:3006/remoteEntry.js"
|
|
20
|
-
|
|
21
|
-
{
|
|
22
|
-
name: "@demo/app3",
|
|
23
|
-
alias: "app3",
|
|
24
|
-
entry: "http://localhost:2001/module-federation-manifest.json"
|
|
19
|
+
entry: "http://localhost:3006/remoteEntry.js",
|
|
20
|
+
alias: "app2"
|
|
25
21
|
},
|
|
26
22
|
],
|
|
27
23
|
});
|
|
28
24
|
|
|
29
25
|
// Load by alias
|
|
30
|
-
loadRemote<{add: (...args: Array<number>)=> number }>("
|
|
26
|
+
loadRemote<{add: (...args: Array<number>)=> number }>("app2/util").then((md)=>{
|
|
31
27
|
md.add(1,2,3);
|
|
32
28
|
});
|
|
33
29
|
```
|
|
@@ -35,74 +31,65 @@ loadRemote<{add: (...args: Array<number>)=> number }>("app3/util").then((md)=>{
|
|
|
35
31
|
### init
|
|
36
32
|
|
|
37
33
|
- Type: `init(options: InitOptions): void`
|
|
38
|
-
-
|
|
34
|
+
- Create runtime instance , it can dynamically register remotes by re-call , but only one instance will exist.
|
|
39
35
|
- InitOptions:
|
|
40
36
|
|
|
41
37
|
```ts
|
|
42
38
|
type InitOptions {
|
|
39
|
+
//The name of the current host
|
|
43
40
|
name: string;
|
|
41
|
+
// The version of the current host will use the host version of the corresponding version online.
|
|
42
|
+
// remoteInfo in remotes will use the online version
|
|
44
43
|
version?: string;
|
|
44
|
+
// In the area where the module is deployed, the consumer will transparently transmit this data to the producer
|
|
45
|
+
//After setting, when the producer data fails to be obtained normally, the backup data will be automatically obtained according to this configuration.
|
|
46
|
+
region?: `EnhancedRegion`;
|
|
47
|
+
// List of dependent remote modules
|
|
48
|
+
// tip: The remotes configured at runtime are not completely consistent with the types and data passed in the build plugin, and the passed in * ^ ~ version rules are not supported at runtime.
|
|
49
|
+
remotes: Array<RemoteInfo>;
|
|
50
|
+
// List of dependencies that need to be shared by the current host
|
|
51
|
+
// When using the build plugin, users can configure the dependencies that need to be shared in the build plugin, and the build plugin will inject the dependencies that need to be shared into the runtime shared configuration.
|
|
52
|
+
// Shared must be manually passed in the version instance reference when it is passed in at runtime, because it cannot be directly passed in at runtime.
|
|
45
53
|
shared?: ShareInfos;
|
|
46
54
|
};
|
|
47
55
|
|
|
48
56
|
type RemoteInfo = (RemotesWithEntry | RemotesWithVersion) & {
|
|
49
|
-
|
|
57
|
+
alias?: string;
|
|
50
58
|
};
|
|
51
59
|
|
|
52
60
|
interface RemotesWithVersion {
|
|
53
|
-
|
|
54
|
-
|
|
61
|
+
name: string;
|
|
62
|
+
version: string;
|
|
55
63
|
}
|
|
56
64
|
|
|
57
65
|
interface RemotesWithEntry {
|
|
58
|
-
|
|
59
|
-
|
|
66
|
+
name: string;
|
|
67
|
+
entry: string;
|
|
60
68
|
}
|
|
61
69
|
|
|
62
70
|
type ShareInfos = {
|
|
63
|
-
|
|
64
|
-
|
|
71
|
+
// Dependent package name, dependent basic information, and sharing strategy
|
|
72
|
+
[pkgName: string]: Share;
|
|
65
73
|
};
|
|
66
74
|
|
|
67
75
|
type Share = {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
76
|
+
// Versions of shared dependencies
|
|
77
|
+
version: string;
|
|
78
|
+
//Which modules consume the current shared dependencies?
|
|
79
|
+
useIn?: Array<string>;
|
|
80
|
+
//Which module does the shared dependency come from?
|
|
81
|
+
from?: string;
|
|
82
|
+
// Get the factory function of the shared dependency instance. When the cached shared instance cannot be loaded, its own shared dependency will be loaded.
|
|
83
|
+
lib: () => Module;
|
|
84
|
+
// Sharing strategy, what strategy will be used to determine the reuse of shared dependencies
|
|
85
|
+
shareConfig?: SharedConfig;
|
|
86
|
+
// Dependencies between shares
|
|
87
|
+
deps?: Array<string>;
|
|
88
|
+
// Under what scope the current shared dependencies are placed, the default is default
|
|
89
|
+
scope?: string | Array<string>;
|
|
82
90
|
};
|
|
83
91
|
```
|
|
84
92
|
|
|
85
|
-
- Example
|
|
86
|
-
|
|
87
|
-
```js
|
|
88
|
-
import { init, loadRemote } from '@module-federation/runtime';
|
|
89
|
-
|
|
90
|
-
init({
|
|
91
|
-
name: '@demo/main-app',
|
|
92
|
-
remotes: [
|
|
93
|
-
{
|
|
94
|
-
name: '@demo/app2',
|
|
95
|
-
entry: 'http://localhost:3006/remoteEntry.js',
|
|
96
|
-
},
|
|
97
|
-
{
|
|
98
|
-
name: '@demo/app3',
|
|
99
|
-
alias: 'app3',
|
|
100
|
-
entry: 'http://localhost:2001/module-federation-manifest.json',
|
|
101
|
-
},
|
|
102
|
-
],
|
|
103
|
-
});
|
|
104
|
-
```
|
|
105
|
-
|
|
106
93
|
### loadRemote
|
|
107
94
|
|
|
108
95
|
- Type: `loadRemote(id: string)`
|
|
@@ -117,18 +104,18 @@ init({
|
|
|
117
104
|
name: '@demo/main-app',
|
|
118
105
|
remotes: [
|
|
119
106
|
{
|
|
120
|
-
name: '@demo/
|
|
121
|
-
alias: '
|
|
122
|
-
entry:
|
|
107
|
+
name: '@demo/app2',
|
|
108
|
+
alias: 'app2',
|
|
109
|
+
entry: "http://localhost:3006/remoteEntry.js",
|
|
123
110
|
},
|
|
124
111
|
],
|
|
125
112
|
});
|
|
126
113
|
|
|
127
114
|
// remoteName + expose
|
|
128
|
-
loadRemote('@demo/
|
|
115
|
+
loadRemote('@demo/app2/util').then((m) => m.add(1, 2, 3));
|
|
129
116
|
|
|
130
117
|
// alias + expose
|
|
131
|
-
loadRemote('
|
|
118
|
+
loadRemote('app2/util').then((m) => m.add(1, 2, 3));
|
|
132
119
|
```
|
|
133
120
|
|
|
134
121
|
### loadShare
|
|
@@ -174,75 +161,11 @@ loadShare('react').then((reactFactory) => {
|
|
|
174
161
|
});
|
|
175
162
|
```
|
|
176
163
|
|
|
177
|
-
### usePlugin
|
|
178
|
-
|
|
179
|
-
Used to extend the internal loading process of `ModuleFederation`, affecting the entire loading process through hook triggers and return values.
|
|
180
|
-
|
|
181
|
-
- Example
|
|
182
|
-
|
|
183
|
-
```ts
|
|
184
|
-
import { init } from '@module-federation/runtime';
|
|
185
|
-
|
|
186
|
-
// mock get remote data remotes config
|
|
187
|
-
function getDataConfig() {
|
|
188
|
-
return new Promise((resolve) => {
|
|
189
|
-
setTimeout(() => {
|
|
190
|
-
resolve({
|
|
191
|
-
remotes: [
|
|
192
|
-
{
|
|
193
|
-
name: '@demo/sub',
|
|
194
|
-
alias: 'sub',
|
|
195
|
-
entry: 'http://localhost:2001/module-federation-manifest.json',
|
|
196
|
-
},
|
|
197
|
-
],
|
|
198
|
-
});
|
|
199
|
-
}, 2000);
|
|
200
|
-
});
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
function RemotesDataPlugin() {
|
|
204
|
-
return {
|
|
205
|
-
name: 'data-config',
|
|
206
|
-
async beforeRequest(args) {
|
|
207
|
-
const remotes = await getDataConfig();
|
|
208
|
-
origin.initOptions({
|
|
209
|
-
remotes,
|
|
210
|
-
});
|
|
211
|
-
return args;
|
|
212
|
-
},
|
|
213
|
-
};
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
init({
|
|
217
|
-
name: '@demo/micro-app',
|
|
218
|
-
remotes: [],
|
|
219
|
-
pluigns: [RemotesDataPlugin()],
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
loadRemote('sub/utils').then((m) => {
|
|
223
|
-
m.add(1, 2, 3, 4);
|
|
224
|
-
});
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
- Type
|
|
228
|
-
|
|
229
|
-
```typescript
|
|
230
|
-
type Plugin = {
|
|
231
|
-
name: string;
|
|
232
|
-
core: {
|
|
233
|
-
beforeRequest: AsyncWaterfallHook<{
|
|
234
|
-
id: string;
|
|
235
|
-
options: Options;
|
|
236
|
-
origin: VmokHost;
|
|
237
|
-
}>;
|
|
238
|
-
};
|
|
239
|
-
snapshot: {};
|
|
240
|
-
};
|
|
241
|
-
type usePlugin = (plugin: Plugin) => void;
|
|
242
|
-
```
|
|
243
|
-
|
|
244
164
|
### preloadRemote
|
|
245
165
|
|
|
166
|
+
- Type: `preloadRemote(preloadOptions: Array<PreloadRemoteArgs>)`
|
|
167
|
+
- Used to preload remote assets like remoteEntry.js .
|
|
168
|
+
|
|
246
169
|
- Type
|
|
247
170
|
|
|
248
171
|
```typescript
|
|
@@ -270,10 +193,12 @@ type PreloadRemoteArgs = {
|
|
|
270
193
|
|
|
271
194
|
- Details
|
|
272
195
|
|
|
196
|
+
**Info**: Only if the entry is manifest can more resources be loaded. The manifest plugin will be supported in 2024.Q1
|
|
197
|
+
|
|
273
198
|
Through `preloadRemote`, module resources can be preloaded at an earlier stage to avoid waterfall requests. `preloadRemote` can preload the following content:
|
|
274
199
|
|
|
275
200
|
- The `remoteEntry` of `remote`
|
|
276
|
-
- `expose` of `remote`
|
|
201
|
+
- `expose` assets of `remote`
|
|
277
202
|
- Synchronous resources or asynchronous resources of `remote`
|
|
278
203
|
- `remote` resources that `remote` depends on
|
|
279
204
|
|
|
@@ -281,6 +206,7 @@ Through `preloadRemote`, module resources can be preloaded at an earlier stage t
|
|
|
281
206
|
|
|
282
207
|
```ts
|
|
283
208
|
import { init, preloadRemote } from '@module-federation/runtime';
|
|
209
|
+
|
|
284
210
|
init({
|
|
285
211
|
name: '@demo/preload-remote',
|
|
286
212
|
remotes: [
|
|
@@ -298,4 +224,467 @@ init({
|
|
|
298
224
|
},
|
|
299
225
|
],
|
|
300
226
|
});
|
|
227
|
+
|
|
228
|
+
// Preload @demo/sub1 module
|
|
229
|
+
// Filter resource information that contains ignore in the resource name
|
|
230
|
+
// Only preload sub-dependent @demo/sub1-button modules
|
|
231
|
+
preloadRemote([
|
|
232
|
+
{
|
|
233
|
+
nameOrAlias: '@demo/sub1',
|
|
234
|
+
filter(assetUrl) {
|
|
235
|
+
return assetUrl.indexOf('ignore') === -1;
|
|
236
|
+
},
|
|
237
|
+
depsRemote: [{ nameOrAlias: '@demo/sub1-button' }],
|
|
238
|
+
},
|
|
239
|
+
]);
|
|
240
|
+
|
|
241
|
+
// Preload @demo/sub2 module
|
|
242
|
+
// Preload all exposes under @demo/sub2
|
|
243
|
+
// Preload the synchronous resources and asynchronous resources of @demo/sub2
|
|
244
|
+
preloadRemote([
|
|
245
|
+
{
|
|
246
|
+
nameOrAlias: '@demo/sub2',
|
|
247
|
+
resourceCategory: 'all',
|
|
248
|
+
},
|
|
249
|
+
]);
|
|
250
|
+
|
|
251
|
+
// Preload expose of @demo/sub3 module
|
|
252
|
+
preloadRemote([
|
|
253
|
+
{
|
|
254
|
+
nameOrAlias: '@demo/sub3',
|
|
255
|
+
resourceCategory: 'all',
|
|
256
|
+
exposes: ['add'],
|
|
257
|
+
},
|
|
258
|
+
]);
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
## hooks
|
|
262
|
+
|
|
263
|
+
Lifecycle hooks for FederationHost interaction.
|
|
264
|
+
|
|
265
|
+
* example
|
|
266
|
+
|
|
267
|
+
```ts
|
|
268
|
+
import { init } from '@module-federation/runtime'
|
|
269
|
+
import type { FederationRuntimePlugin } from '@module-federation/runtime';
|
|
270
|
+
|
|
271
|
+
const runtimePlugin: () => FederationRuntimePlugin =
|
|
272
|
+
function () {
|
|
273
|
+
return {
|
|
274
|
+
name: 'my-runtime-plugin',
|
|
275
|
+
beforeInit(args) {
|
|
276
|
+
console.log('beforeInit: ', args);
|
|
277
|
+
return args;
|
|
278
|
+
},
|
|
279
|
+
beforeRequest(args) {
|
|
280
|
+
console.log('beforeRequest: ', args);
|
|
281
|
+
return args;
|
|
282
|
+
},
|
|
283
|
+
afterResolve(args) {
|
|
284
|
+
console.log('afterResolve', args);
|
|
285
|
+
return args;
|
|
286
|
+
},
|
|
287
|
+
onLoad(args) {
|
|
288
|
+
console.log('onLoad: ', args);
|
|
289
|
+
return args;
|
|
290
|
+
},
|
|
291
|
+
async loadShare(args) {
|
|
292
|
+
console.log('loadShare:', args);
|
|
293
|
+
},
|
|
294
|
+
async beforeLoadShare(args) {
|
|
295
|
+
console.log('beforeloadShare:', args);
|
|
296
|
+
return args;
|
|
297
|
+
},
|
|
298
|
+
};
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
init({
|
|
302
|
+
name: '@demo/app-main',
|
|
303
|
+
remotes: [
|
|
304
|
+
{
|
|
305
|
+
name: "@demo/app2",
|
|
306
|
+
entry: "http://localhost:3006/remoteEntry.js",
|
|
307
|
+
alias: "app2"
|
|
308
|
+
},
|
|
309
|
+
],
|
|
310
|
+
plugins: [runtimePlugin()]
|
|
311
|
+
});
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### beforeInit
|
|
315
|
+
|
|
316
|
+
`SyncWaterfallHook`
|
|
317
|
+
|
|
318
|
+
Updates Federation Host configurations before the initialization process of remote containers.
|
|
319
|
+
|
|
320
|
+
* type
|
|
321
|
+
|
|
322
|
+
```ts
|
|
323
|
+
function beforeInit(args: BeforeInitOptions): BeforeInitOptions
|
|
324
|
+
|
|
325
|
+
type BeforeInitOptions ={
|
|
326
|
+
userOptions: UserOptions;
|
|
327
|
+
options: FederationRuntimeOptions;
|
|
328
|
+
origin: FederationHost;
|
|
329
|
+
shareInfo: ShareInfos;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
interface FederationRuntimeOptions {
|
|
333
|
+
id?: string;
|
|
334
|
+
name: string;
|
|
335
|
+
version?: string;
|
|
336
|
+
remotes: Array<Remote>;
|
|
337
|
+
shared: ShareInfos;
|
|
338
|
+
plugins: Array<FederationRuntimePlugin>;
|
|
339
|
+
inBrowser: boolean;
|
|
340
|
+
}
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### init
|
|
344
|
+
|
|
345
|
+
`SyncHook`
|
|
346
|
+
|
|
347
|
+
Called during the initialization of remote containers.
|
|
348
|
+
|
|
349
|
+
* type
|
|
350
|
+
|
|
351
|
+
```ts
|
|
352
|
+
function init(args: InitOptions): void
|
|
353
|
+
|
|
354
|
+
type InitOptions ={
|
|
355
|
+
options: FederationRuntimeOptions;
|
|
356
|
+
origin: FederationHost;
|
|
357
|
+
}
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
### beforeRequest
|
|
361
|
+
|
|
362
|
+
`AsyncWaterfallHook`
|
|
363
|
+
|
|
364
|
+
Invoked before resolving a remote container, useful for injecting the container or updating something ahead of the lookup.
|
|
365
|
+
|
|
366
|
+
* type
|
|
367
|
+
|
|
368
|
+
```ts
|
|
369
|
+
async function beforeRequest(args: BeforeRequestOptions): Promise<BeforeRequestOptions>
|
|
370
|
+
|
|
371
|
+
type BeforeRequestOptions ={
|
|
372
|
+
id: string;
|
|
373
|
+
options: FederationRuntimeOptions;
|
|
374
|
+
origin: FederationHost;
|
|
375
|
+
}
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
### afterResolve
|
|
379
|
+
|
|
380
|
+
`AsyncWaterfallHook`
|
|
381
|
+
|
|
382
|
+
Called after resolving a container, allowing redirection or modification of resolved information.
|
|
383
|
+
|
|
384
|
+
* type
|
|
385
|
+
|
|
386
|
+
```ts
|
|
387
|
+
async function afterResolve(args: AfterResolveOptions): Promise<AfterResolveOptions>
|
|
388
|
+
|
|
389
|
+
type AfterResolveOptions ={
|
|
390
|
+
id: string;
|
|
391
|
+
pkgNameOrAlias: string;
|
|
392
|
+
expose: string;
|
|
393
|
+
remote: Remote;
|
|
394
|
+
options: FederationRuntimeOptions;
|
|
395
|
+
origin: FederationHost;
|
|
396
|
+
remoteInfo: RemoteInfo;
|
|
397
|
+
remoteSnapshot?: ModuleInfo;
|
|
398
|
+
}
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
### onLoad
|
|
402
|
+
|
|
403
|
+
`AsyncHook`
|
|
404
|
+
|
|
405
|
+
Triggered once a federated module is loaded, allowing access and modification to the exports of the loaded file.
|
|
406
|
+
|
|
407
|
+
* type
|
|
408
|
+
|
|
409
|
+
```ts
|
|
410
|
+
async function onLoad(args: OnLoadOptions): Promise<void>
|
|
411
|
+
|
|
412
|
+
type OnLoadOptions ={
|
|
413
|
+
id: string;
|
|
414
|
+
expose: string;
|
|
415
|
+
pkgNameOrAlias: string;
|
|
416
|
+
remote: Remote;
|
|
417
|
+
options: ModuleOptions;
|
|
418
|
+
origin: FederationHost;
|
|
419
|
+
exposeModule: any;
|
|
420
|
+
exposeModuleFactory: any;
|
|
421
|
+
moduleInstance: Module;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
type ModuleOptions = {
|
|
425
|
+
remoteInfo: RemoteInfo;
|
|
426
|
+
host: FederationHost;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
interface RemoteInfo {
|
|
430
|
+
name: string;
|
|
431
|
+
version?: string;
|
|
432
|
+
buildVersion?: string;
|
|
433
|
+
entry: string;
|
|
434
|
+
type: RemoteEntryType;
|
|
435
|
+
entryGlobalName: string;
|
|
436
|
+
shareScope: string;
|
|
437
|
+
}
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
### handlePreloadModule
|
|
441
|
+
|
|
442
|
+
`SyncHook`
|
|
443
|
+
|
|
444
|
+
Handles preloading logic for federated modules.
|
|
445
|
+
|
|
446
|
+
* type
|
|
447
|
+
|
|
448
|
+
```ts
|
|
449
|
+
function handlePreloadModule(args: HandlePreloadModuleOptions): void
|
|
450
|
+
|
|
451
|
+
type HandlePreloadModuleOptions ={
|
|
452
|
+
id: string;
|
|
453
|
+
name: string;
|
|
454
|
+
remoteSnapshot: ModuleInfo;
|
|
455
|
+
preloadConfig: PreloadRemoteArgs;
|
|
456
|
+
}
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
### errorLoadRemote
|
|
460
|
+
|
|
461
|
+
`AsyncHook`
|
|
462
|
+
|
|
463
|
+
Invoked if loading a federated module fails, enabling custom error handling.
|
|
464
|
+
|
|
465
|
+
* type
|
|
466
|
+
|
|
467
|
+
```ts
|
|
468
|
+
async function errorLoadRemote(args: ErrorLoadRemoteOptions): Promise<void | unknown>
|
|
469
|
+
|
|
470
|
+
type ErrorLoadRemoteOptions ={
|
|
471
|
+
id: string;
|
|
472
|
+
error: unknown;
|
|
473
|
+
from: 'build' | 'runtime';
|
|
474
|
+
origin: FederationHost;
|
|
475
|
+
}
|
|
476
|
+
```
|
|
477
|
+
* example
|
|
478
|
+
|
|
479
|
+
```ts
|
|
480
|
+
import { init, loadRemote } from '@module-federation/runtime'
|
|
481
|
+
|
|
482
|
+
import type { FederationRuntimePlugin } from '@module-federation/runtime';
|
|
483
|
+
|
|
484
|
+
const fallbackPlugin: () => FederationRuntimePlugin =
|
|
485
|
+
function () {
|
|
486
|
+
return {
|
|
487
|
+
name: 'fallback-plugin',
|
|
488
|
+
errorLoadRemote(args) {
|
|
489
|
+
const fallback = 'fallback'
|
|
490
|
+
return fallback;
|
|
491
|
+
},
|
|
492
|
+
};
|
|
493
|
+
};
|
|
494
|
+
|
|
495
|
+
|
|
496
|
+
init({
|
|
497
|
+
name: '@demo/app-main',
|
|
498
|
+
remotes: [
|
|
499
|
+
{
|
|
500
|
+
name: "@demo/app2",
|
|
501
|
+
entry: "http://localhost:3006/remoteEntry.js",
|
|
502
|
+
alias: "app2"
|
|
503
|
+
},
|
|
504
|
+
],
|
|
505
|
+
plugins: [fallbackPlugin()]
|
|
506
|
+
});
|
|
507
|
+
|
|
508
|
+
loadRemote('app2/un-existed-module').then(mod=>{
|
|
509
|
+
expect(mod).toEqual('fallback');
|
|
510
|
+
})
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
### beforeLoadShare
|
|
514
|
+
|
|
515
|
+
`AsyncWaterfallHook`
|
|
516
|
+
|
|
517
|
+
Called before attempting to load or negotiate shared modules between federated apps.
|
|
518
|
+
|
|
519
|
+
* type
|
|
520
|
+
|
|
521
|
+
```ts
|
|
522
|
+
async function beforeLoadShare(args: BeforeLoadShareOptions): Promise<BeforeLoadShareOptions>
|
|
523
|
+
|
|
524
|
+
type BeforeLoadShareOptions ={
|
|
525
|
+
pkgName: string;
|
|
526
|
+
shareInfo?: Shared;
|
|
527
|
+
shared: Options['shared'];
|
|
528
|
+
origin: FederationHost;
|
|
529
|
+
}
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
### resolveShare
|
|
533
|
+
|
|
534
|
+
`SyncWaterfallHook`
|
|
535
|
+
|
|
536
|
+
Allows manual resolution of shared module requests.
|
|
537
|
+
|
|
538
|
+
* type
|
|
539
|
+
|
|
540
|
+
```ts
|
|
541
|
+
function resolveShare(args: ResolveShareOptions): ResolveShareOptions
|
|
542
|
+
|
|
543
|
+
type ResolveShareOptions ={
|
|
544
|
+
shareScopeMap: ShareScopeMap;
|
|
545
|
+
scope: string;
|
|
546
|
+
pkgName: string;
|
|
547
|
+
version: string;
|
|
548
|
+
GlobalFederation: Federation;
|
|
549
|
+
resolver: () => Shared | undefined;
|
|
550
|
+
}
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
* example
|
|
554
|
+
|
|
555
|
+
```ts
|
|
556
|
+
import { init, loadRemote } from '@module-federation/runtime'
|
|
557
|
+
|
|
558
|
+
import type { FederationRuntimePlugin } from '@module-federation/runtime';
|
|
559
|
+
|
|
560
|
+
const customSharedPlugin: () => FederationRuntimePlugin =
|
|
561
|
+
function () {
|
|
562
|
+
return {
|
|
563
|
+
name: 'custom-shared-plugin',
|
|
564
|
+
resolveShare(args) {
|
|
565
|
+
const { shareScopeMap, scope, pkgName, version, GlobalFederation } = args;
|
|
566
|
+
|
|
567
|
+
if (
|
|
568
|
+
pkgName !== 'react'
|
|
569
|
+
) {
|
|
570
|
+
return args;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
args.resolver = function () {
|
|
574
|
+
shareScopeMap[scope][pkgName][version] = window.React; // replace local share scope manually with desired module
|
|
575
|
+
return shareScopeMap[scope][pkgName][version];
|
|
576
|
+
};
|
|
577
|
+
return args;
|
|
578
|
+
},
|
|
579
|
+
};
|
|
580
|
+
};
|
|
581
|
+
|
|
582
|
+
|
|
583
|
+
init({
|
|
584
|
+
name: '@demo/app-main',
|
|
585
|
+
shared: {
|
|
586
|
+
react: {
|
|
587
|
+
version: '17.0.0',
|
|
588
|
+
scope: 'default',
|
|
589
|
+
lib: () => React,
|
|
590
|
+
shareConfig: {
|
|
591
|
+
singleton: true,
|
|
592
|
+
requiredVersion: '^17.0.0',
|
|
593
|
+
},
|
|
594
|
+
},
|
|
595
|
+
},
|
|
596
|
+
plugins: [customSharedPlugin()]
|
|
597
|
+
});
|
|
598
|
+
|
|
599
|
+
window.React = ()=> 'Desired Shared';
|
|
600
|
+
|
|
601
|
+
loadShare("react").then((reactFactory)=>{
|
|
602
|
+
expect(reactFactory()).toEqual(window.React());
|
|
603
|
+
});
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
### beforePreloadRemote
|
|
607
|
+
|
|
608
|
+
`AsyncHook`
|
|
609
|
+
|
|
610
|
+
Invoked before any preload logic is executed by the preload handler.
|
|
611
|
+
|
|
612
|
+
* type
|
|
613
|
+
|
|
614
|
+
```ts
|
|
615
|
+
async function beforePreloadRemote(args: BeforePreloadRemoteOptions): BeforePreloadRemoteOptions
|
|
616
|
+
|
|
617
|
+
type BeforePreloadRemoteOptions ={
|
|
618
|
+
preloadOps: Array<PreloadRemoteArgs>;
|
|
619
|
+
options: Options;
|
|
620
|
+
origin: FederationHost;
|
|
621
|
+
}
|
|
622
|
+
```
|
|
623
|
+
|
|
624
|
+
### generatePreloadAssets
|
|
625
|
+
|
|
626
|
+
`AsyncHook`
|
|
627
|
+
|
|
628
|
+
Called for generating preload assets based on configurations.
|
|
629
|
+
|
|
630
|
+
* type
|
|
631
|
+
|
|
632
|
+
```ts
|
|
633
|
+
async function generatePreloadAssets(args: GeneratePreloadAssetsOptions): Promise<PreloadAssets>
|
|
634
|
+
|
|
635
|
+
type GeneratePreloadAssetsOptions ={
|
|
636
|
+
origin: FederationHost;
|
|
637
|
+
preloadOptions: PreloadOptions[number];
|
|
638
|
+
remote: Remote;
|
|
639
|
+
remoteInfo: RemoteInfo;
|
|
640
|
+
remoteSnapshot: ModuleInfo;
|
|
641
|
+
globalSnapshot: GlobalModuleInfo;
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
interface PreloadAssets {
|
|
645
|
+
cssAssets: Array<string>;
|
|
646
|
+
jsAssetsWithoutEntry: Array<string>;
|
|
647
|
+
entryAssets: Array<EntryAssets>;
|
|
648
|
+
}
|
|
649
|
+
```
|
|
650
|
+
|
|
651
|
+
## loaderHook
|
|
652
|
+
|
|
653
|
+
Plugin system for module loading operations.
|
|
654
|
+
|
|
655
|
+
### createScript
|
|
656
|
+
|
|
657
|
+
`SyncHook`
|
|
658
|
+
|
|
659
|
+
* type
|
|
660
|
+
|
|
661
|
+
```ts
|
|
662
|
+
function createScript(args: CreateScriptOptions): HTMLScriptElement | void
|
|
663
|
+
|
|
664
|
+
type CreateScriptOptions ={
|
|
665
|
+
url: string;
|
|
666
|
+
}
|
|
667
|
+
```
|
|
668
|
+
|
|
669
|
+
* example
|
|
670
|
+
|
|
671
|
+
```ts
|
|
672
|
+
import { init } from '@module-federation/runtime'
|
|
673
|
+
import type { FederationRuntimePlugin } from '@module-federation/runtime';
|
|
674
|
+
|
|
675
|
+
const changeScriptAttributePlugin: () => FederationRuntimePlugin =
|
|
676
|
+
function () {
|
|
677
|
+
return {
|
|
678
|
+
name: 'change-script-attribute',
|
|
679
|
+
createScript({ url }) {
|
|
680
|
+
if (url === testRemoteEntry) {
|
|
681
|
+
let script = document.createElement('script');
|
|
682
|
+
script.src = testRemoteEntry;
|
|
683
|
+
script.setAttribute('loader-hooks', 'isTrue');
|
|
684
|
+
script.setAttribute('crossorigin', 'anonymous');
|
|
685
|
+
return script;
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
};
|
|
689
|
+
};
|
|
301
690
|
```
|