Skip to content

Commit ce0597e

Browse files
2heal1zhoushaw
andauthored
feat: add registerRemotes api (#2171)
Co-authored-by: Zhou xiao <[email protected]>
1 parent d36a4d7 commit ce0597e

File tree

10 files changed

+332
-39
lines changed

10 files changed

+332
-39
lines changed

.changeset/swift-boats-cough.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@module-federation/runtime': patch
3+
---
4+
5+
feat: add registerRemotes api

packages/runtime/README.md

Lines changed: 70 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -212,15 +212,15 @@ init({
212212
remotes: [
213213
{
214214
name: '@demo/sub1',
215-
entry: 'http://localhost:2001/vmok-manifest.json',
215+
entry: 'http://localhost:2001/mf-manifest.json',
216216
},
217217
{
218218
name: '@demo/sub2',
219-
entry: 'http://localhost:2001/vmok-manifest.json',
219+
entry: 'http://localhost:2001/mf-manifest.json',
220220
},
221221
{
222222
name: '@demo/sub3',
223-
entry: 'http://localhost:2001/vmok-manifest.json',
223+
entry: 'http://localhost:2001/mf-manifest.json',
224224
},
225225
],
226226
});
@@ -258,6 +258,73 @@ preloadRemote([
258258
]);
259259
```
260260

261+
### registerRemotes
262+
263+
- Type: `registerRemotes(remotes: Remote[], options?: { force?: boolean }): void`
264+
- Used to register remotes after init .
265+
266+
- Type
267+
268+
```typescript
269+
function registerRemotes(remotes: Remote[], options?: { force?: boolean }) {}
270+
271+
type Remote = (RemoteWithEntry | RemoteWithVersion) & RemoteInfoCommon;
272+
273+
interface RemoteInfoCommon {
274+
alias?: string;
275+
shareScope?: string;
276+
type?: RemoteEntryType;
277+
entryGlobalName?: string;
278+
}
279+
280+
interface RemoteWithEntry {
281+
name: string;
282+
entry: string;
283+
}
284+
285+
interface RemoteWithVersion {
286+
name: string;
287+
version: string;
288+
}
289+
```
290+
291+
- Details
292+
**info**: Please be careful when setting `force:true` !
293+
294+
If set `force: true`, it will merge remote(include loaded remote), and remove loaded remote cache , as well as console.warn to tell this action may have risks.
295+
296+
* Example
297+
298+
```ts
299+
import { init, registerRemotes } from '@module-federation/runtime';
300+
301+
init({
302+
name: '@demo/register-new-remotes',
303+
remotes: [
304+
{
305+
name: '@demo/sub1',
306+
entry: 'http://localhost:2001/mf-manifest.json',
307+
}
308+
],
309+
});
310+
311+
// add new remote @demo/sub2
312+
registerRemotes([
313+
{
314+
name: '@demo/sub2',
315+
entry: 'http://localhost:2002/mf-manifest.json',
316+
}
317+
]);
318+
319+
// override previous remote @demo/sub1
320+
registerRemotes([
321+
{
322+
name: '@demo/sub1',
323+
entry: 'http://localhost:2003/mf-manifest.json',
324+
}
325+
]);
326+
```
327+
261328
## hooks
262329

263330
Lifecycle hooks for FederationHost interaction.
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import { assert, describe, test, it } from 'vitest';
2+
import { FederationHost } from '../src/index';
3+
4+
describe('FederationHost', () => {
5+
it('register new remotes', async () => {
6+
const FM = new FederationHost({
7+
name: '@federation/instance',
8+
version: '1.0.1',
9+
remotes: [
10+
{
11+
name: '@register-remotes/app1',
12+
entry:
13+
'http://localhost:1111/resources/register-remotes/app1/federation-remote-entry.js',
14+
},
15+
],
16+
});
17+
18+
const app1Module = await FM.loadRemote<Promise<() => string>>(
19+
'@register-remotes/app1/say',
20+
);
21+
assert(app1Module);
22+
const app1Res = await app1Module();
23+
expect(app1Res).toBe('hello app1 entry1');
24+
25+
// register new remotes
26+
FM.registerRemotes([
27+
{
28+
name: '@register-remotes/app2',
29+
entry:
30+
'http://localhost:1111/resources/register-remotes/app2/federation-remote-entry.js',
31+
},
32+
]);
33+
const app2Module = await FM.loadRemote<Promise<() => string>>(
34+
'@register-remotes/app2/say',
35+
);
36+
assert(app2Module);
37+
const res = await app2Module();
38+
expect(res).toBe('hello app2');
39+
});
40+
41+
it('will not merge loaded remote by default', async () => {
42+
const FM = new FederationHost({
43+
name: '@federation/instance',
44+
version: '1.0.1',
45+
remotes: [
46+
{
47+
name: '@register-remotes/app1',
48+
entry:
49+
'http://localhost:1111/resources/register-remotes/app1/federation-remote-entry.js',
50+
},
51+
],
52+
});
53+
FM.registerRemotes([
54+
{
55+
name: '@register-remotes/app1',
56+
// entry is different from the registered remote
57+
entry:
58+
'http://localhost:1111/resources/register-remotes/app1/federation-remote-entry2.js',
59+
},
60+
]);
61+
62+
const app1Module = await FM.loadRemote<Promise<() => string>>(
63+
'@register-remotes/app1/say',
64+
);
65+
assert(app1Module);
66+
const app1Res = await app1Module();
67+
expect(app1Res).toBe('hello app1 entry1');
68+
});
69+
70+
it('merge loaded remote by setting "force:true"', async () => {
71+
const FM = new FederationHost({
72+
name: '@federation/instance',
73+
version: '1.0.1',
74+
remotes: [
75+
{
76+
name: '@register-remotes/app1',
77+
entry:
78+
'http://localhost:1111/resources/register-remotes/app1/federation-remote-entry.js',
79+
},
80+
],
81+
});
82+
const app1Module = await FM.loadRemote<Promise<() => string>>(
83+
'@register-remotes/app1/say',
84+
);
85+
assert(app1Module);
86+
const app1Res = await app1Module();
87+
expect(app1Res).toBe('hello app1 entry1');
88+
89+
FM.registerRemotes(
90+
[
91+
{
92+
name: '@register-remotes/app1',
93+
// entry is different from the registered remote
94+
entry:
95+
'http://localhost:1111/resources/register-remotes/app1/federation-remote-entry2.js',
96+
},
97+
],
98+
{ force: true },
99+
);
100+
const newApp1Module = await FM.loadRemote<Promise<() => string>>(
101+
'@register-remotes/app1/say',
102+
);
103+
assert(newApp1Module);
104+
const newApp1Res = await newApp1Module();
105+
// value is different from the registered remote
106+
expect(newApp1Res).toBe('hello app1 entry2');
107+
});
108+
});
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
globalThis[`@register-remotes/app1`] = {
2+
get(scope) {
3+
const moduleMap = {
4+
'./say'() {
5+
return () => 'hello app1 entry1';
6+
},
7+
};
8+
return moduleMap[scope];
9+
},
10+
init() {},
11+
};
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
globalThis[`@register-remotes/app1`] = {
2+
get(scope) {
3+
const moduleMap = {
4+
'./say'() {
5+
return () => 'hello app1 entry2';
6+
},
7+
};
8+
return moduleMap[scope];
9+
},
10+
init() {},
11+
};
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
globalThis[`@register-remotes/app2`] = {
2+
get(scope) {
3+
const moduleMap = {
4+
'./say'() {
5+
return () => 'hello app2';
6+
},
7+
};
8+
return moduleMap[scope];
9+
},
10+
init() {},
11+
};

packages/runtime/src/core.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,12 @@ initializeSharing(shareScopeName?: string): boolean | Promise<boolean>
7979
```
8080
Initializes sharing sequences for shared scopes.
8181

82+
### `registerRemotes`
83+
```typescript
84+
registerRemotes(remotes: Remote[], options?: { force?: boolean }): void
85+
```
86+
Register remotes after init.
87+
8288
## Hooks
8389
`FederationHost` offers various lifecycle hooks for interacting at different stages of the module federation process. These hooks include:
8490

0 commit comments

Comments
 (0)