Skip to content

Commit d641c94

Browse files
clydinalan-agius4
authored andcommitted
refactor(@angular-devkit/build-angular): lazily initialize JS transformer worker pool
The Worker thread pool that is used by the JavaScript Transformer within the application builder is now only initialized if there is JavaScript that must be transformed. This removes any overhead associated with the worker pool if no work is required. This is particularly useful when using the development server with caching enabled and all the dependencies have already been prebundled.
1 parent d539286 commit d641c94

File tree

1 file changed

+29
-16
lines changed

1 file changed

+29
-16
lines changed

packages/angular_devkit/build_angular/src/tools/esbuild/javascript-transformer.ts

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,13 @@ export interface JavaScriptTransformerOptions {
2626
* and advanced optimizations.
2727
*/
2828
export class JavaScriptTransformer {
29-
#workerPool: Piscina;
29+
#workerPool: Piscina | undefined;
3030
#commonOptions: Required<JavaScriptTransformerOptions>;
3131

32-
constructor(options: JavaScriptTransformerOptions, maxThreads: number) {
33-
this.#workerPool = new Piscina({
34-
filename: require.resolve('./javascript-transformer-worker'),
35-
minThreads: 1,
36-
maxThreads,
37-
// Shutdown idle threads after 1 second of inactivity
38-
idleTimeout: 1000,
39-
});
40-
32+
constructor(
33+
options: JavaScriptTransformerOptions,
34+
readonly maxThreads: number,
35+
) {
4136
// Extract options to ensure only the named options are serialized and sent to the worker
4237
const {
4338
sourcemap,
@@ -53,6 +48,18 @@ export class JavaScriptTransformer {
5348
};
5449
}
5550

51+
#ensureWorkerPool(): Piscina {
52+
this.#workerPool ??= new Piscina({
53+
filename: require.resolve('./javascript-transformer-worker'),
54+
minThreads: 1,
55+
maxThreads: this.maxThreads,
56+
// Shutdown idle threads after 1 second of inactivity
57+
idleTimeout: 1000,
58+
});
59+
60+
return this.#workerPool;
61+
}
62+
5663
/**
5764
* Performs JavaScript transformations on a file from the filesystem.
5865
* If no transformations are required, the data for the original file will be returned.
@@ -63,7 +70,7 @@ export class JavaScriptTransformer {
6370
transformFile(filename: string, skipLinker?: boolean): Promise<Uint8Array> {
6471
// Always send the request to a worker. Files are almost always from node modules which means
6572
// they may need linking. The data is also not yet available to perform most transformation checks.
66-
return this.#workerPool.run({
73+
return this.#ensureWorkerPool().run({
6774
filename,
6875
skipLinker,
6976
...this.#commonOptions,
@@ -92,7 +99,7 @@ export class JavaScriptTransformer {
9299
);
93100
}
94101

95-
return this.#workerPool.run({
102+
return this.#ensureWorkerPool().run({
96103
filename,
97104
data,
98105
skipLinker,
@@ -104,10 +111,16 @@ export class JavaScriptTransformer {
104111
* Stops all active transformation tasks and shuts down all workers.
105112
* @returns A void promise that resolves when closing is complete.
106113
*/
107-
close(): Promise<void> {
108-
// Workaround piscina bug where a worker thread will be recreated after destroy to meet the minimum.
109-
this.#workerPool.options.minThreads = 0;
114+
async close(): Promise<void> {
115+
if (this.#workerPool) {
116+
// Workaround piscina bug where a worker thread will be recreated after destroy to meet the minimum.
117+
this.#workerPool.options.minThreads = 0;
110118

111-
return this.#workerPool.destroy();
119+
try {
120+
await this.#workerPool.destroy();
121+
} finally {
122+
this.#workerPool = undefined;
123+
}
124+
}
112125
}
113126
}

0 commit comments

Comments
 (0)