Skip to content

Commit 2097daa

Browse files
zhoushawzhouxiao.shaw
and
zhouxiao.shaw
authored
feat(runtime): automatically complete the snapshot so that devtool can visualize it (#1982)
Co-authored-by: zhouxiao.shaw <[email protected]>
1 parent af8672e commit 2097daa

15 files changed

+261
-250
lines changed

.changeset/odd-tomatoes-fetch.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(runtime): automatically complete the snapshot so that devtool can visualize it

packages/runtime/__tests__/global.spec.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { assert, describe, test, it, vi } from 'vitest';
22
import { init } from '../src/index';
3+
import { getInfoWithoutType } from '../src/global';
34

45
describe('global', () => {
56
it('inject mode', () => {
@@ -16,4 +17,31 @@ describe('global', () => {
1617
injectArgs,
1718
);
1819
});
20+
21+
it('getInfoWithoutType', () => {
22+
const snapshot = {
23+
'@federation/app1': 1,
24+
'@federation/app2': 2,
25+
'app:@federation/app3': 3,
26+
'npm:@federation/app4': 4,
27+
};
28+
29+
const res = getInfoWithoutType(snapshot, '@federation/app1');
30+
expect(res).toMatchObject({
31+
key: '@federation/app1',
32+
value: 1,
33+
});
34+
35+
const res2 = getInfoWithoutType(snapshot, '@federation/app3' as any);
36+
expect(res2).toMatchObject({
37+
key: 'app:@federation/app3',
38+
value: 3,
39+
});
40+
41+
const res3 = getInfoWithoutType(snapshot, '@federation/app4' as any);
42+
expect(res3).toMatchObject({
43+
key: 'npm:@federation/app4',
44+
value: 4,
45+
});
46+
});
1947
});

packages/runtime/__tests__/hooks.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,8 @@ describe('hooks', () => {
186186
);
187187
assert(res);
188188
expect(res()).toBe('hello app2');
189-
// @ts-ignore fakeSrc is local mock attr, which value is the same as src
190189
const testLoadedScript = [...document.querySelectorAll('script')].find(
190+
// @ts-ignore fakeSrc is local mock attr, which value is the same as src
191191
(script) => script.fakeSrc === testRemoteEntry,
192192
);
193193
assert(testLoadedScript);

packages/runtime/__tests__/load-remote.spec.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,12 @@ import { assert, describe, it } from 'vitest';
33
import { FederationHost, init } from '../src/index';
44
import { mockRemoteSnapshot } from './mock/utils';
55
import { matchRemoteWithNameAndExpose } from '../src/utils/manifest';
6-
import { addGlobalSnapshot, getGlobalSnapshot, Global } from '../src/global';
6+
import {
7+
addGlobalSnapshot,
8+
getGlobalSnapshot,
9+
Global,
10+
setGlobalFederationConstructor,
11+
} from '../src/global';
712
import { requestList } from './mock/env';
813

914
describe('matchRemote', () => {
@@ -395,7 +400,7 @@ describe('loadRemote with manifest.json', () => {
395400
});
396401

397402
it('circulate deps', async () => {
398-
globalThis.__FEDERATION__.__DEBUG_CONSTRUCTOR__ = FederationHost;
403+
setGlobalFederationConstructor(FederationHost, true);
399404
const FM = init({
400405
name: '@circulate-deps/app1',
401406
remotes: [
@@ -415,7 +420,7 @@ describe('loadRemote with manifest.json', () => {
415420
expect(res).toBe('@circulate-deps/app2');
416421

417422
Global.__FEDERATION__.__INSTANCES__ = [];
418-
globalThis.__FEDERATION__.__DEBUG_CONSTRUCTOR__ = undefined;
423+
setGlobalFederationConstructor(undefined, true);
419424
});
420425

421426
it('manifest.json with query', async () => {
@@ -479,6 +484,10 @@ describe('lazy loadRemote add remote into snapshot', () => {
479484
});
480485
const snapshot = getGlobalSnapshot();
481486
const hostModuleInfo = snapshot['@demo/app1'];
487+
assert(
488+
hostModuleInfo && 'remotesInfo' in hostModuleInfo,
489+
'hostModuleInfo Cannot be empty',
490+
);
482491
const beforeHostRemotesInfo = hostModuleInfo.remotesInfo;
483492
const beforeRemotesLength = Object.keys(beforeHostRemotesInfo).length;
484493
expect(beforeRemotesLength).toBe(0);
@@ -519,6 +528,10 @@ describe('lazy loadRemote add remote into snapshot', () => {
519528
});
520529
const snapshot = getGlobalSnapshot();
521530
const hostModuleInfo = snapshot['@demo/app1'];
531+
assert(
532+
hostModuleInfo && 'remotesInfo' in hostModuleInfo,
533+
'hostModuleInfo Cannot be empty',
534+
);
522535
const beforeHostRemotesInfo = hostModuleInfo.remotesInfo;
523536
const beforeRemotesLength = Object.keys(beforeHostRemotesInfo).length;
524537
expect(beforeRemotesLength).toBe(0);
@@ -595,7 +608,7 @@ describe('loadRemote', () => {
595608
);
596609
// @ts-ignore fakeSrc is local mock attr, which value is the same as src
597610
const loadedSrcs = [...document.querySelectorAll('script')].map(
598-
(i) => i.fakeSrc,
611+
(i) => (i as any).fakeSrc,
599612
);
600613
expect(loadedSrcs.includes(`${remotePublicPath}${jsSyncAssetPath}`));
601614
reset();
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"id": "@snapshot/remote1",
3+
"name": "@snapshot/remote1",
4+
"metaData": {
5+
"name": "@snapshot/remote1",
6+
"publicPath": "http://localhost:1111/",
7+
"type": "app",
8+
"globalName": "@snapshot/remote1",
9+
"buildInfo": {
10+
"buildVersion": "custom"
11+
},
12+
"remoteEntry": {
13+
"name": "federation-remote-entry.js",
14+
"path": "resources/snapshot/remote1"
15+
},
16+
"types": {
17+
"name": "index.d.ts",
18+
"path": "./"
19+
}
20+
},
21+
"remotes": [],
22+
"shared": [],
23+
"exposes": []
24+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
globalThis[`@snapshot/remote1`] = {
2+
get(scope) {
3+
const moduleMap = {
4+
'./say'() {
5+
return () => 'hello world "@snapshot/remote1"';
6+
},
7+
};
8+
return moduleMap[scope];
9+
},
10+
init() {},
11+
};
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"id": "@snapshot/remote2",
3+
"name": "@snapshot/remote2",
4+
"metaData": {
5+
"name": "@snapshot/remote2",
6+
"publicPath": "http://localhost:1111/",
7+
"type": "app",
8+
"globalName": "@snapshot/remote2",
9+
"buildInfo": {
10+
"buildVersion": "custom"
11+
},
12+
"remoteEntry": {
13+
"name": "federation-remote-entry.js",
14+
"path": "resources/snapshot/remote2"
15+
},
16+
"types": {
17+
"name": "index.d.ts",
18+
"path": "./"
19+
}
20+
},
21+
"remotes": [],
22+
"shared": [],
23+
"exposes": []
24+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
globalThis[`@snapshot/remote2`] = {
2+
get(scope) {
3+
const moduleMap = {
4+
'./say'() {
5+
return () => 'hello world "@snapshot/remote2"';
6+
},
7+
};
8+
return moduleMap[scope];
9+
},
10+
init() {},
11+
};

packages/runtime/__tests__/share.ts

Lines changed: 3 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { GlobalShareScope, Options } from '../src/type';
1+
import { GlobalShareScopeMap, Options } from '../src/type';
22
export const mergeShareInfo1 = {
33
name: '@federation/merge-shared',
44
remotes: [],
@@ -68,6 +68,7 @@ export const localMergeShareInfos: Options['shared'] = {
6868
scope: ['default'],
6969
useIn: [],
7070
deps: [],
71+
strategy: 'version-first',
7172
},
7273
'react-dom': {
7374
version: '17.0.0',
@@ -81,83 +82,6 @@ export const localMergeShareInfos: Options['shared'] = {
8182
scope: ['default', 'sub2'],
8283
useIn: [],
8384
deps: [],
84-
},
85-
};
86-
87-
export const globalMergeShareInfos: GlobalShareScope = {
88-
default: {
89-
react: {
90-
'16.0.0': {
91-
version: '16.0.0',
92-
from: mergeShareInfo1.name,
93-
get: mergeShareInfo1.shared.react.get,
94-
shareConfig: {
95-
singleton: false,
96-
requiredVersion: '^16.0.0',
97-
eager: false,
98-
},
99-
scope: ['default'],
100-
useIn: [],
101-
deps: [],
102-
},
103-
},
104-
'react-dom': {
105-
'17.0.0': {
106-
version: '17.0.0',
107-
from: mergeShareInfo2.name,
108-
get: mergeShareInfo2.shared['react-dom'].get,
109-
shareConfig: {
110-
singleton: false,
111-
requiredVersion: '^16.0.0',
112-
eager: false,
113-
},
114-
scope: ['default', 'sub2'],
115-
useIn: [],
116-
deps: [],
117-
},
118-
'16.0.0': {
119-
version: '16.0.0',
120-
from: mergeShareInfo3.name,
121-
get: mergeShareInfo3.shared['react-dom'].get,
122-
shareConfig: {
123-
singleton: false,
124-
requiredVersion: '^16.0.0',
125-
eager: false,
126-
},
127-
scope: ['default', 'sub2'],
128-
useIn: [],
129-
deps: [],
130-
},
131-
},
132-
},
133-
sub2: {
134-
'react-dom': {
135-
'16.0.0': {
136-
version: '16.0.0',
137-
from: mergeShareInfo3.name,
138-
get: mergeShareInfo3.shared['react-dom'].get,
139-
shareConfig: {
140-
singleton: false,
141-
requiredVersion: '^16.0.0',
142-
eager: false,
143-
},
144-
scope: ['default', 'sub2'],
145-
useIn: [],
146-
deps: [],
147-
},
148-
'17.0.0': {
149-
version: '17.0.0',
150-
from: mergeShareInfo2.name,
151-
get: mergeShareInfo2.shared['react-dom'].get,
152-
shareConfig: {
153-
singleton: false,
154-
requiredVersion: '^16.0.0',
155-
eager: false,
156-
},
157-
scope: ['default', 'sub2'],
158-
useIn: [],
159-
deps: [],
160-
},
161-
},
85+
strategy: 'version-first',
16286
},
16387
};

0 commit comments

Comments
 (0)