Skip to content

Commit 752537b

Browse files
authored
fix(runtime): use loaded or loading shared if sharedStrategy is loaded-first (#3176)
1 parent 849ef9c commit 752537b

File tree

3 files changed

+269
-3
lines changed

3 files changed

+269
-3
lines changed

.changeset/bright-guests-sip.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+
fix(runtime): use loaded or loading shared if sharedStrategy is loaded-first
Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
import { describe, it, expect } from 'vitest';
2+
import { getRegisteredShare } from '../src/utils/share';
3+
import { assert } from '../src/utils/logger';
4+
5+
describe('get expected shared', () => {
6+
it('get loading shared if sharedStrategy is "loaded-first"', () => {
7+
let res;
8+
const promise = new Promise((resolve) => {
9+
// pending
10+
res = resolve;
11+
});
12+
const shareScopeMap = {
13+
default: {
14+
react: {
15+
'18.2.0': {
16+
deps: [],
17+
useIn: [],
18+
from: 'host',
19+
get: () => {
20+
//noop
21+
},
22+
loaded: undefined,
23+
loading: promise,
24+
lib: undefined,
25+
version: '18.2.0',
26+
scope: ['default'],
27+
shareConfig: {
28+
requiredVersion: '^18.2.0',
29+
singleton: 1,
30+
eager: 0,
31+
strictVersion: false,
32+
},
33+
strategy: 'loaded-first',
34+
},
35+
'18.3.1': {
36+
deps: [],
37+
useIn: [],
38+
from: 'remote',
39+
loaded: undefined,
40+
get: () => {
41+
//noop
42+
},
43+
loading: null,
44+
version: '18.3.1',
45+
scope: ['default'],
46+
shareConfig: {
47+
requiredVersion: '^18.3.1',
48+
singleton: 1,
49+
eager: 0,
50+
strictVersion: false,
51+
},
52+
strategy: 'loaded-first',
53+
},
54+
},
55+
},
56+
};
57+
58+
const shareInfoRes = {
59+
deps: [],
60+
useIn: [],
61+
from: 'remote',
62+
loaded: undefined,
63+
get: () => {
64+
//noop
65+
},
66+
loading: null,
67+
version: '18.3.1',
68+
scope: ['default'],
69+
shareConfig: {
70+
fixedDependencies: false,
71+
requiredVersion: '18.3.1',
72+
strictVersion: false,
73+
singleton: true,
74+
eager: false,
75+
},
76+
strategy: 'loaded-first',
77+
};
78+
79+
// @ts-ignore
80+
const registeredShared = getRegisteredShare(
81+
shareScopeMap,
82+
'react',
83+
shareInfoRes,
84+
{
85+
emit: () => undefined,
86+
},
87+
);
88+
assert(registeredShared, 'must get registeredShared');
89+
expect(registeredShared.from).toEqual('host');
90+
res();
91+
});
92+
93+
it('get loaded shared if it has been loaded and sharedStrategy is "loaded-first"', () => {
94+
const shareScopeMap = {
95+
default: {
96+
react: {
97+
'18.2.0': {
98+
deps: [],
99+
useIn: [],
100+
from: 'host',
101+
get: () => {
102+
//noop
103+
},
104+
loaded: true,
105+
lib: {},
106+
loading: Promise.resolve(),
107+
version: '18.2.0',
108+
scope: ['default'],
109+
shareConfig: {
110+
requiredVersion: '^18.2.0',
111+
singleton: 1,
112+
eager: 0,
113+
strictVersion: false,
114+
},
115+
strategy: 'loaded-first',
116+
},
117+
'18.3.1': {
118+
deps: [],
119+
useIn: [],
120+
from: 'remote',
121+
loaded: undefined,
122+
get: () => {
123+
//noop
124+
},
125+
loading: null,
126+
version: '18.3.1',
127+
scope: ['default'],
128+
shareConfig: {
129+
requiredVersion: '^18.3.1',
130+
singleton: 1,
131+
eager: 0,
132+
strictVersion: false,
133+
},
134+
strategy: 'loaded-first',
135+
},
136+
},
137+
},
138+
};
139+
140+
const shareInfoRes = {
141+
deps: [],
142+
useIn: [],
143+
from: 'remote',
144+
loaded: undefined,
145+
get: () => {
146+
//noop
147+
},
148+
loading: null,
149+
version: '18.3.1',
150+
scope: ['default'],
151+
shareConfig: {
152+
fixedDependencies: false,
153+
requiredVersion: '18.3.1',
154+
strictVersion: false,
155+
singleton: true,
156+
eager: false,
157+
},
158+
strategy: 'loaded-first',
159+
};
160+
161+
// @ts-ignore
162+
const registeredShared = getRegisteredShare(
163+
shareScopeMap,
164+
'react',
165+
shareInfoRes,
166+
{
167+
emit: () => undefined,
168+
},
169+
);
170+
assert(registeredShared, 'must get registeredShared');
171+
expect(registeredShared.from).toEqual('host');
172+
});
173+
174+
it('get max version shared if all registered shared no loaded or loading and sharedStrategy is "loaded-first"', () => {
175+
const shareScopeMap = {
176+
default: {
177+
react: {
178+
'18.2.0': {
179+
deps: [],
180+
useIn: [],
181+
from: 'host',
182+
get: () => {
183+
//noop
184+
},
185+
loaded: undefined,
186+
lib: undefined,
187+
loading: null,
188+
version: '18.2.0',
189+
scope: ['default'],
190+
shareConfig: {
191+
requiredVersion: '^18.2.0',
192+
singleton: 1,
193+
eager: 0,
194+
strictVersion: false,
195+
},
196+
strategy: 'loaded-first',
197+
},
198+
'18.3.1': {
199+
deps: [],
200+
useIn: [],
201+
from: 'remote',
202+
loaded: undefined,
203+
get: () => {
204+
//noop
205+
},
206+
loading: null,
207+
version: '18.3.1',
208+
scope: ['default'],
209+
shareConfig: {
210+
requiredVersion: '^18.3.1',
211+
singleton: 1,
212+
eager: 0,
213+
strictVersion: false,
214+
},
215+
strategy: 'loaded-first',
216+
},
217+
},
218+
},
219+
};
220+
221+
const shareInfoRes = {
222+
deps: [],
223+
useIn: [],
224+
from: 'remote',
225+
loaded: undefined,
226+
get: () => {
227+
//noop
228+
},
229+
loading: null,
230+
version: '18.3.1',
231+
scope: ['default'],
232+
shareConfig: {
233+
fixedDependencies: false,
234+
requiredVersion: '18.3.1',
235+
strictVersion: false,
236+
singleton: true,
237+
eager: false,
238+
},
239+
strategy: 'loaded-first',
240+
};
241+
242+
// @ts-ignore
243+
const registeredShared = getRegisteredShare(
244+
shareScopeMap,
245+
'react',
246+
shareInfoRes,
247+
{
248+
emit: () => undefined,
249+
},
250+
);
251+
assert(registeredShared, 'must get registeredShared');
252+
expect(registeredShared.from).toEqual('remote');
253+
});
254+
});

packages/runtime/src/utils/share.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,10 @@ export const isLoaded = (shared: Shared) => {
152152
return Boolean(shared.loaded) || typeof shared.lib === 'function';
153153
};
154154

155+
const isLoading = (shared: Shared) => {
156+
return Boolean(shared.loading);
157+
};
158+
155159
function findSingletonVersionOrderByVersion(
156160
shareScopeMap: ShareScopeMap,
157161
scope: string,
@@ -173,14 +177,17 @@ function findSingletonVersionOrderByLoaded(
173177
const versions = shareScopeMap[scope][pkgName];
174178

175179
const callback = function (prev: string, cur: string): boolean {
176-
if (isLoaded(versions[cur])) {
177-
if (isLoaded(versions[prev])) {
180+
const isLoadingOrLoaded = (shared: Shared) => {
181+
return isLoaded(shared) || isLoading(shared);
182+
};
183+
if (isLoadingOrLoaded(versions[cur])) {
184+
if (isLoadingOrLoaded(versions[prev])) {
178185
return Boolean(versionLt(prev, cur));
179186
} else {
180187
return true;
181188
}
182189
}
183-
if (isLoaded(versions[prev])) {
190+
if (isLoadingOrLoaded(versions[prev])) {
184191
return false;
185192
}
186193
return versionLt(prev, cur);

0 commit comments

Comments
 (0)