Skip to content

Commit 22fcccd

Browse files
authored
perf(dts-plugin): add fetch timeout and add log (#3554)
1 parent 1010f96 commit 22fcccd

File tree

10 files changed

+53
-16
lines changed

10 files changed

+53
-16
lines changed

.changeset/seven-geckos-carry.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@module-federation/dts-plugin': patch
3+
'@module-federation/sdk': patch
4+
---
5+
6+
perf(dts-plugin): add fetch timeout and add log

packages/dts-plugin/src/core/configurations/hostPlugin.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ describe('hostPlugin', () => {
4242
consumeAPITypes: false,
4343
runtimePkgs: [],
4444
remoteTypeUrls: {},
45+
timeout: 60000,
4546
});
4647

4748
expect(mapRemotesToDownload).toStrictEqual({
@@ -68,6 +69,7 @@ describe('hostPlugin', () => {
6869
consumeAPITypes: false,
6970
runtimePkgs: [],
7071
remoteTypeUrls: {},
72+
timeout: 60000,
7173
};
7274

7375
const { hostOptions, mapRemotesToDownload } =

packages/dts-plugin/src/core/configurations/hostPlugin.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ const defaultOptions = {
1818
consumeAPITypes: false,
1919
runtimePkgs: [],
2020
remoteTypeUrls: {},
21+
timeout: 60000,
2122
} satisfies Partial<HostOptions>;
2223

2324
const buildZipUrl = (hostOptions: Required<HostOptions>, url: string) => {

packages/dts-plugin/src/core/lib/DTSManager.general.spec.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,8 @@ describe('DTSManager General Tests', () => {
154154
url: 'http://example.com/remote.manifest.json',
155155
alias: 'test-alias',
156156
};
157-
158-
const result = await dtsManager.requestRemoteManifest(remoteInfo);
157+
// @ts-expect-error only need timeout, which is not required
158+
const result = await dtsManager.requestRemoteManifest(remoteInfo, {});
159159
expect(result.zipUrl).toBeDefined();
160160
expect(result.apiTypeUrl).toBeDefined();
161161
expect(result.zipUrl).toContain('http://example.com/types.zip');
@@ -181,7 +181,8 @@ describe('DTSManager General Tests', () => {
181181
alias: 'test-alias',
182182
};
183183

184-
const result = await dtsManager.requestRemoteManifest(remoteInfo);
184+
// @ts-expect-error only need timeout, which is not required
185+
const result = await dtsManager.requestRemoteManifest(remoteInfo, {});
185186
expect(result.zipUrl).toBeDefined();
186187
expect(result.apiTypeUrl).toBe('');
187188
});
@@ -195,7 +196,8 @@ describe('DTSManager General Tests', () => {
195196
alias: 'test-alias',
196197
};
197198

198-
const result = await dtsManager.requestRemoteManifest(remoteInfo);
199+
// @ts-expect-error only need timeout, which is not required
200+
const result = await dtsManager.requestRemoteManifest(remoteInfo, {});
199201
expect(result).toEqual(remoteInfo);
200202
});
201203

@@ -220,7 +222,8 @@ describe('DTSManager General Tests', () => {
220222
alias: 'test-alias',
221223
};
222224

223-
const result = await dtsManager.requestRemoteManifest(remoteInfo);
225+
// @ts-expect-error only need timeout, which is not required
226+
const result = await dtsManager.requestRemoteManifest(remoteInfo, {});
224227
expect(result.zipUrl).toContain('http://example.com/custom/types.zip');
225228
expect(result.apiTypeUrl).toContain('http://example.com/custom/api.d.ts');
226229
});
@@ -242,6 +245,7 @@ describe('DTSManager General Tests', () => {
242245
abortOnError: false,
243246
consumeAPITypes: true,
244247
maxRetries: 3,
248+
timeout: 60000,
245249
};
246250

247251
it('should successfully download types archive', async () => {
@@ -347,7 +351,8 @@ describe('DTSManager General Tests', () => {
347351
vi.mocked(axios.get).mockResolvedValueOnce({ data: apiTypeContent });
348352
vi.spyOn(fs, 'writeFileSync');
349353

350-
await dtsManager.downloadAPITypes(remoteInfo, '/tmp/types');
354+
// @ts-expect-error only need timeout, which is not required
355+
await dtsManager.downloadAPITypes(remoteInfo, '/tmp/types', {});
351356

352357
expect(fs.writeFileSync).toHaveBeenCalled();
353358
const writeCall = vi.mocked(fs.writeFileSync).mock.calls[0];

packages/dts-plugin/src/core/lib/DTSManager.ts

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ class DTSManager {
205205

206206
async requestRemoteManifest(
207207
remoteInfo: RemoteInfo,
208+
hostOptions: Required<HostOptions>,
208209
): Promise<Required<RemoteInfo>> {
209210
try {
210211
if (!remoteInfo.url.includes(MANIFEST_EXT)) {
@@ -214,7 +215,7 @@ class DTSManager {
214215
return remoteInfo as Required<RemoteInfo>;
215216
}
216217
const url = remoteInfo.url;
217-
const res = await axiosGet(url);
218+
const res = await axiosGet(url, { timeout: hostOptions.timeout });
218219
const manifestJson = res.data as unknown as Manifest;
219220
if (!manifestJson.metaData.types.zip) {
220221
throw new Error(`Can not get ${remoteInfo.name}'s types archive url!`);
@@ -280,14 +281,15 @@ class DTSManager {
280281
async downloadAPITypes(
281282
remoteInfo: Required<RemoteInfo>,
282283
destinationPath: string,
284+
hostOptions: Required<HostOptions>,
283285
) {
284286
const { apiTypeUrl } = remoteInfo;
285287
if (!apiTypeUrl) {
286288
return;
287289
}
288290
try {
289291
const url = apiTypeUrl;
290-
const res = await axiosGet(url);
292+
const res = await axiosGet(url, { timeout: hostOptions.timeout });
291293
let apiTypeFile = res.data as string;
292294
apiTypeFile = apiTypeFile.replaceAll(
293295
REMOTE_ALIAS_IDENTIFIER,
@@ -389,8 +391,10 @@ class DTSManager {
389391
async (item) => {
390392
const remoteInfo = item[1];
391393
if (!this.remoteAliasMap[remoteInfo.alias]) {
392-
const requiredRemoteInfo =
393-
await this.requestRemoteManifest(remoteInfo);
394+
const requiredRemoteInfo = await this.requestRemoteManifest(
395+
remoteInfo,
396+
hostOptions,
397+
);
394398
this.remoteAliasMap[remoteInfo.alias] = requiredRemoteInfo;
395399
}
396400

@@ -434,7 +438,11 @@ class DTSManager {
434438
return;
435439
}
436440

437-
await this.downloadAPITypes(remoteInfo, destinationPath);
441+
await this.downloadAPITypes(
442+
remoteInfo,
443+
destinationPath,
444+
hostOptions,
445+
);
438446
}),
439447
);
440448
this.consumeAPITypes(hostOptions);
@@ -507,6 +515,7 @@ class DTSManager {
507515
const addNew = await this.downloadAPITypes(
508516
requiredRemoteInfo,
509517
destinationPath,
518+
hostOptions,
510519
);
511520
if (addNew) {
512521
this.consumeAPITypes(hostOptions);
@@ -531,8 +540,10 @@ class DTSManager {
531540
);
532541
if (remoteInfo) {
533542
if (!this.remoteAliasMap[remoteInfo.alias]) {
534-
const requiredRemoteInfo =
535-
await this.requestRemoteManifest(remoteInfo);
543+
const requiredRemoteInfo = await this.requestRemoteManifest(
544+
remoteInfo,
545+
hostOptions,
546+
);
536547
this.remoteAliasMap[remoteInfo.alias] = requiredRemoteInfo;
537548
}
538549
await consumeTypes(this.remoteAliasMap[remoteInfo.alias]);
@@ -550,7 +561,7 @@ class DTSManager {
550561
});
551562
fileLog(`start request manifest`, 'consumeTypes', 'info');
552563
this.updatedRemoteInfos[updatedRemoteInfo.name] =
553-
await this.requestRemoteManifest(parsedRemoteInfo);
564+
await this.requestRemoteManifest(parsedRemoteInfo, hostOptions);
554565
fileLog(
555566
`end request manifest, this.updatedRemoteInfos[updatedRemoteInfo.name]: ${JSON.stringify(
556567
this.updatedRemoteInfos[updatedRemoteInfo.name],

packages/dts-plugin/src/core/lib/archiveHandler.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ export const downloadTypesArchive = (hostOptions: Required<HostOptions>) => {
6262
const url = fileToDownload;
6363
const response = await axiosGet(url, {
6464
responseType: 'arraybuffer',
65+
timeout: hostOptions.timeout,
6566
}).catch(downloadErrorLogger(destinationFolder, url));
6667
if (
6768
typeof response.headers?.['content-type'] === 'string' &&

packages/dts-plugin/src/core/lib/utils.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,5 +154,6 @@ export async function axiosGet(url: string, config?: AxiosRequestConfig) {
154154
headers: getEnvHeaders(),
155155
},
156156
...config,
157+
timeout: config?.timeout || 60000,
157158
});
158159
}

packages/dts-plugin/src/plugins/ConsumeTypesPlugin.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1-
import type { Compiler, WebpackPluginInstance } from 'webpack';
1+
import { logger } from '@module-federation/sdk';
22
import {
33
normalizeOptions,
44
type moduleFederationPlugin,
55
} from '@module-federation/sdk';
66
import { validateOptions, consumeTypes } from '../core/index';
77
import { isPrd } from './utils';
88

9+
import type { Compiler, WebpackPluginInstance } from 'webpack';
10+
911
export class ConsumeTypesPlugin implements WebpackPluginInstance {
1012
pluginOptions: moduleFederationPlugin.ModuleFederationPluginOptions;
1113
dtsOptions: moduleFederationPlugin.PluginDtsOptions;
@@ -70,6 +72,7 @@ export class ConsumeTypesPlugin implements WebpackPluginInstance {
7072
typeof normalizedConsumeTypes.remoteTypeUrls === 'function'
7173
? normalizedConsumeTypes.remoteTypeUrls()
7274
: Promise.resolve(normalizedConsumeTypes.remoteTypeUrls);
75+
logger.debug('start fetching remote types...');
7376
const promise = fetchRemoteTypeUrlsPromise.then((remoteTypeUrls) => {
7477
consumeTypes({
7578
...finalOptions,
@@ -97,6 +100,7 @@ export class ConsumeTypesPlugin implements WebpackPluginInstance {
97100
async () => {
98101
// await consume types promise to make sure the consumer not throw types error
99102
await promise;
103+
logger.debug('fetch remote types success!');
100104
},
101105
);
102106
});

packages/dts-plugin/src/plugins/GenerateTypesPlugin.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import type { Compilation, Compiler, WebpackPluginInstance } from 'webpack';
21
import fs from 'fs';
32
import path from 'path';
43
import { isDev, getCompilerOutputDir } from './utils';
54
import {
5+
logger,
66
normalizeOptions,
77
type moduleFederationPlugin,
88
} from '@module-federation/sdk';
@@ -14,6 +14,8 @@ import {
1414
type DTSManagerOptions,
1515
} from '../core/index';
1616

17+
import type { Compilation, Compiler, WebpackPluginInstance } from 'webpack';
18+
1719
export class GenerateTypesPlugin implements WebpackPluginInstance {
1820
pluginOptions: moduleFederationPlugin.ModuleFederationPluginOptions;
1921
dtsOptions: moduleFederationPlugin.PluginDtsOptions;
@@ -119,7 +121,9 @@ export class GenerateTypesPlugin implements WebpackPluginInstance {
119121
return;
120122
}
121123

124+
logger.debug('start generating types...');
122125
await generateTypesFn(finalOptions);
126+
logger.debug('generate types success!');
123127
const config = finalOptions.remote.moduleFederationConfig;
124128
let zipPrefix = '';
125129
if (typeof config.manifest === 'object' && config.manifest.filePath) {
@@ -229,6 +233,7 @@ export class GenerateTypesPlugin implements WebpackPluginInstance {
229233
if (finalOptions.displayErrorInTerminal) {
230234
console.error('Error in mf:generateTypes processAssets hook:', err);
231235
}
236+
logger.debug('generate types fail!');
232237
}
233238
};
234239

packages/sdk/src/types/plugins/ModuleFederationPlugin.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ export interface DtsHostOptions {
154154
consumeAPITypes?: boolean;
155155
runtimePkgs?: string[];
156156
remoteTypeUrls?: (() => Promise<RemoteTypeUrls>) | RemoteTypeUrls;
157+
timeout?: number;
157158
}
158159

159160
export interface DtsRemoteOptions {

0 commit comments

Comments
 (0)