Skip to content

Commit 4fd33fb

Browse files
authored
fix(runtime): throw RUNTIME-008 Error when script resources load failed (#3348)
1 parent 5675773 commit 4fd33fb

File tree

6 files changed

+47
-9
lines changed

6 files changed

+47
-9
lines changed

.changeset/smart-crabs-burn.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@module-federation/error-codes': patch
3+
'@module-federation/runtime': patch
4+
'@module-federation/sdk': patch
5+
---
6+
7+
fix: throw RUNTIME-008 Error when script resources load failed

packages/error-codes/src/desc.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
RUNTIME_005,
77
RUNTIME_006,
88
RUNTIME_007,
9+
RUNTIME_008,
910
TYPE_001,
1011
} from './error-codes';
1112

@@ -17,6 +18,7 @@ export const runtimeDescMap = {
1718
[RUNTIME_005]: 'Invalid loadShareSync function call from bundler runtime',
1819
[RUNTIME_006]: 'Invalid loadShareSync function call from runtime',
1920
[RUNTIME_007]: 'Failed to get remote snapshot.',
21+
[RUNTIME_008]: 'Failed to load script resources.',
2022
};
2123

2224
export const typeDescMap = {

packages/error-codes/src/error-codes.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ export const RUNTIME_004 = 'RUNTIME-004';
55
export const RUNTIME_005 = 'RUNTIME-005';
66
export const RUNTIME_006 = 'RUNTIME-006';
77
export const RUNTIME_007 = 'RUNTIME-007';
8+
export const RUNTIME_008 = 'RUNTIME-008';
89

910
export const TYPE_001 = 'TYPE-001';

packages/runtime/src/utils/load.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { Remote, RemoteEntryExports, RemoteInfo } from '../type';
1111
import { assert } from './logger';
1212
import {
1313
RUNTIME_001,
14+
RUNTIME_008,
1415
getShortErrorMsg,
1516
runtimeDescMap,
1617
} from '@module-federation/error-codes';
@@ -129,6 +130,13 @@ async function loadEntryScript({
129130
return entryExports;
130131
})
131132
.catch((e) => {
133+
assert(
134+
undefined,
135+
getShortErrorMsg(RUNTIME_008, runtimeDescMap, {
136+
remoteName: name,
137+
resourceUrl: entry,
138+
}),
139+
);
132140
throw e;
133141
});
134142
}

packages/sdk/__tests__/dom.spec.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,18 +252,19 @@ describe('createLink', () => {
252252
it('should call the callback when the link fails to load', () => {
253253
const url = 'https://example.com/script.js';
254254
const cb = jest.fn();
255+
const onErrorCallback = jest.fn();
255256
const { link, needAttach } = createLink({
256257
url,
257258
cb,
259+
onErrorCallback,
258260
attrs: { as: 'script' },
259261
});
260262

261263
if (needAttach) {
262264
document.head.appendChild(link);
263265
}
264266
link?.onerror?.(new Event('error'));
265-
266-
expect(cb).toHaveBeenCalled();
267+
expect(onErrorCallback).toHaveBeenCalled();
267268
});
268269

269270
it('should use the link element returned by createLinkHook', () => {

packages/sdk/src/dom.ts

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export function isStaticResourcesEqual(url1: string, url2: string): boolean {
2626
export function createScript(info: {
2727
url: string;
2828
cb?: (value: void | PromiseLike<void>) => void;
29+
onErrorCallback?: (error: Error) => void;
2930
attrs?: Record<string, any>;
3031
needDeleteScript?: boolean;
3132
createScriptHook?: CreateScriptHookDom;
@@ -36,6 +37,7 @@ export function createScript(info: {
3637
let timeout = 20000;
3738
let timeoutId: NodeJS.Timeout;
3839
const scripts = document.getElementsByTagName('script');
40+
3941
for (let i = 0; i < scripts.length; i++) {
4042
const s = scripts[i];
4143
const scriptSrc = s.getAttribute('src');
@@ -88,6 +90,14 @@ export function createScript(info: {
8890
event: any,
8991
): Promise<void> => {
9092
clearTimeout(timeoutId);
93+
const onScriptCompleteCallback = () => {
94+
if (event?.type === 'error') {
95+
info?.onErrorCallback && info?.onErrorCallback(event);
96+
} else {
97+
info?.cb && info?.cb();
98+
}
99+
};
100+
91101
// Prevent memory leaks in IE.
92102
if (script) {
93103
script.onerror = null;
@@ -102,14 +112,14 @@ export function createScript(info: {
102112
const result = (prev as any)(event);
103113
if (result instanceof Promise) {
104114
const res = await result;
105-
info?.cb?.();
115+
onScriptCompleteCallback();
106116
return res;
107117
}
108-
info?.cb?.();
118+
onScriptCompleteCallback();
109119
return result;
110120
}
111121
}
112-
info?.cb?.();
122+
onScriptCompleteCallback();
113123
};
114124

115125
script.onerror = onScriptComplete.bind(null, script.onerror);
@@ -127,7 +137,8 @@ export function createScript(info: {
127137

128138
export function createLink(info: {
129139
url: string;
130-
cb: (value: void | PromiseLike<void>) => void;
140+
cb?: (value: void | PromiseLike<void>) => void;
141+
onErrorCallback?: (error: Error) => void;
131142
attrs: Record<string, string>;
132143
needDeleteLink?: boolean;
133144
createLinkHook?: (
@@ -184,6 +195,13 @@ export function createLink(info: {
184195
// eslint-disable-next-line @typescript-eslint/no-explicit-any
185196
event: any,
186197
): void => {
198+
const onLinkCompleteCallback = () => {
199+
if (event?.type === 'error') {
200+
info?.onErrorCallback && info?.onErrorCallback(event);
201+
} else {
202+
info?.cb && info?.cb();
203+
}
204+
};
187205
// Prevent memory leaks in IE.
188206
if (link) {
189207
link.onerror = null;
@@ -197,11 +215,11 @@ export function createLink(info: {
197215
if (prev) {
198216
// eslint-disable-next-line @typescript-eslint/no-explicit-any
199217
const res = (prev as any)(event);
200-
info.cb();
218+
onLinkCompleteCallback();
201219
return res;
202220
}
203221
}
204-
info.cb();
222+
onLinkCompleteCallback();
205223
};
206224

207225
link.onerror = onLinkComplete.bind(null, link.onerror);
@@ -218,10 +236,11 @@ export function loadScript(
218236
},
219237
) {
220238
const { attrs = {}, createScriptHook } = info;
221-
return new Promise<void>((resolve, _reject) => {
239+
return new Promise<void>((resolve, reject) => {
222240
const { script, needAttach } = createScript({
223241
url,
224242
cb: resolve,
243+
onErrorCallback: reject,
225244
attrs: {
226245
fetchpriority: 'high',
227246
...attrs,

0 commit comments

Comments
 (0)