Skip to content

Commit 24ba96e

Browse files
authored
fix: handle circular init shared (#2876)
1 parent 865c00b commit 24ba96e

File tree

6 files changed

+59
-17
lines changed

6 files changed

+59
-17
lines changed

.changeset/itchy-ducks-crash.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@module-federation/webpack-bundler-runtime': patch
3+
'@module-federation/runtime': patch
4+
---
5+
6+
fix: handle circular init shared

packages/runtime/src/core.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import {
1111
ShareScopeMap,
1212
InitScope,
1313
RemoteEntryInitOptions,
14+
InitTokens,
15+
CallFrom,
1416
} from './type';
1517
import { getBuilderId, registerPlugins } from './utils';
1618
import { Module } from './module';
@@ -170,9 +172,13 @@ export class FederationHost {
170172

171173
initializeSharing(
172174
shareScopeName = DEFAULT_SCOPE,
173-
strategy?: Shared['strategy'],
175+
extraOptions?: {
176+
initScope?: InitScope;
177+
from?: CallFrom;
178+
strategy?: Shared['strategy'];
179+
},
174180
): Array<Promise<void>> {
175-
return this.sharedHandler.initializeSharing(shareScopeName, strategy);
181+
return this.sharedHandler.initializeSharing(shareScopeName, extraOptions);
176182
}
177183

178184
initRawContainer(
@@ -193,7 +199,7 @@ export class FederationHost {
193199
// eslint-disable-next-line @typescript-eslint/member-ordering
194200
async loadRemote<T>(
195201
id: string,
196-
options?: { loadFactory?: boolean; from: 'build' | 'runtime' },
202+
options?: { loadFactory?: boolean; from: CallFrom },
197203
): Promise<T | null> {
198204
return this.remoteHandler.loadRemote(id, options);
199205
}

packages/runtime/src/remote/index.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
Remote,
1515
RemoteInfo,
1616
RemoteEntryExports,
17+
CallFrom,
1718
} from '../type';
1819
import { FederationHost } from '../core';
1920
import {
@@ -97,7 +98,7 @@ export class RemoteHandler {
9798
id: string;
9899
error: unknown;
99100
options?: any;
100-
from: 'build' | 'runtime';
101+
from: CallFrom;
101102
lifecycle: 'onLoad' | 'beforeRequest';
102103
origin: FederationHost;
103104
},
@@ -178,7 +179,7 @@ export class RemoteHandler {
178179
// eslint-disable-next-line @typescript-eslint/member-ordering
179180
async loadRemote<T>(
180181
id: string,
181-
options?: { loadFactory?: boolean; from: 'build' | 'runtime' },
182+
options?: { loadFactory?: boolean; from: CallFrom },
182183
): Promise<T | null> {
183184
const { host } = this;
184185
try {

packages/runtime/src/shared/index.ts

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ import {
77
RemoteEntryExports,
88
UserOptions,
99
ShareStrategy,
10+
InitScope,
11+
InitTokens,
12+
CallFrom,
1013
} from '../type';
1114
import { FederationHost } from '../core';
1215
import {
@@ -55,10 +58,11 @@ export class SharedHandler {
5558
hostShareScopeMap?: ShareScopeMap;
5659
}>('initContainerShareScopeMap'),
5760
});
58-
61+
initTokens: InitTokens;
5962
constructor(host: FederationHost) {
6063
this.host = host;
6164
this.shareScopeMap = {};
65+
this.initTokens = {};
6266
this._setGlobalShareScopeMap(host.options);
6367
}
6468

@@ -121,7 +125,9 @@ export class SharedHandler {
121125
await Promise.all(
122126
shareInfo.scope.map(async (shareScope) => {
123127
await Promise.all(
124-
this.initializeSharing(shareScope, shareInfo.strategy),
128+
this.initializeSharing(shareScope, {
129+
strategy: shareInfo.strategy,
130+
}),
125131
);
126132
return;
127133
}),
@@ -242,9 +248,26 @@ export class SharedHandler {
242248
// eslint-disable-next-line @typescript-eslint/member-ordering
243249
initializeSharing(
244250
shareScopeName = DEFAULT_SCOPE,
245-
strategy?: ShareStrategy,
251+
extraOptions?: {
252+
initScope?: InitScope;
253+
from?: CallFrom;
254+
strategy?: ShareStrategy;
255+
},
246256
): Array<Promise<void>> {
247257
const { host } = this;
258+
const from = extraOptions?.from;
259+
const strategy = extraOptions?.strategy;
260+
let initScope = extraOptions?.initScope;
261+
const promises: Promise<any>[] = [];
262+
if (from !== 'build') {
263+
const { initTokens } = this;
264+
if (!initScope) initScope = [];
265+
let initToken = initTokens[shareScopeName];
266+
if (!initToken)
267+
initToken = initTokens[shareScopeName] = { from: this.host.name };
268+
if (initScope.indexOf(initToken) >= 0) return promises;
269+
initScope.push(initToken);
270+
}
248271

249272
const shareScope = this.shareScopeMap;
250273
const hostName = host.options.name;
@@ -274,9 +297,8 @@ export class SharedHandler {
274297
versions[version] = shared;
275298
}
276299
};
277-
const promises: Promise<any>[] = [];
278300
const initFn = (mod: RemoteEntryExports) =>
279-
mod && mod.init && mod.init(shareScope[shareScopeName]);
301+
mod && mod.init && mod.init(shareScope[shareScopeName], initScope);
280302

281303
const initRemoteModule = async (key: string): Promise<void> => {
282304
const { module } = await host.remoteHandler.getRemoteModuleAndOptions({
@@ -285,7 +307,7 @@ export class SharedHandler {
285307
if (module.getEntry) {
286308
const entry = await module.getEntry();
287309
if (!module.inited) {
288-
initFn(entry);
310+
await initFn(entry);
289311
module.inited = true;
290312
}
291313
}
@@ -333,7 +355,7 @@ export class SharedHandler {
333355

334356
if (shareInfo?.scope) {
335357
shareInfo.scope.forEach((shareScope) => {
336-
this.initializeSharing(shareScope, shareInfo.strategy);
358+
this.initializeSharing(shareScope, { strategy: shareInfo.strategy });
337359
});
338360
}
339361
const registeredShared = getRegisteredShare(

packages/runtime/src/type/config.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,9 @@ export type RemoteEntryInitOptions = {
133133
shareScopeMap: ShareScopeMap;
134134
};
135135

136-
export type InitScope = Array<Record<string, never>>;
137-
136+
export type InitTokens = Record<string, Record<string, any>>;
137+
export type InitScope = InitTokens[];
138+
export type CallFrom = 'build' | 'runtime';
138139
export type RemoteEntryExports = {
139140
get: (id: string) => () => Promise<Module>;
140141
init: (

packages/webpack-bundler-runtime/src/initializeSharing.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,12 @@ export function initializeSharing({
1010
initScope,
1111
}: InitializeSharingOptions): Promise<boolean> | boolean | void {
1212
if (!initScope) initScope = [];
13+
const mfInstance = webpackRequire.federation.instance!;
14+
1315
// handling circular init calls
1416
var initToken = initTokens[shareScopeName];
15-
if (!initToken) initToken = initTokens[shareScopeName] = {};
17+
if (!initToken)
18+
initToken = initTokens[shareScopeName] = { from: mfInstance.name };
1619
if (initScope.indexOf(initToken) >= 0) return;
1720
initScope.push(initToken);
1821

@@ -42,8 +45,11 @@ export function initializeSharing({
4245
handleError(err);
4346
}
4447
};
45-
const promises =
46-
webpackRequire.federation.instance!.initializeSharing(shareScopeName);
48+
const promises = mfInstance.initializeSharing(shareScopeName, {
49+
strategy: mfInstance.options.shareStrategy,
50+
initScope,
51+
from: 'build',
52+
});
4753
attachShareScopeMap(webpackRequire);
4854

4955
const bundlerRuntimeRemotesOptions =

0 commit comments

Comments
 (0)