Skip to content

Commit a02db0a

Browse files
clydinalan-agius4
authored andcommitted
refactor(@angular-devkit/build-angular): allow JS transformer result reuse for application dev-server builder
The `JavaScriptTransformer` class that is responsible for Angular linking and several build optimization transformations can now be configured to track and reuse previous and pending transformation requests. This allows for cases where multiple consumers of the class will not cause repeat transformation actions. Pending results will be stored if the constructor option `reuseResults` is enabled. If two transformation requests are issued for the same file, the same underlying result will be provided to each. This behavior currently only applies to file transformation requests. (cherry picked from commit 988dce6)
1 parent 323b005 commit a02db0a

File tree

2 files changed

+25
-7
lines changed

2 files changed

+25
-7
lines changed

packages/angular_devkit/build_angular/src/builders/dev-server/vite-server.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ export async function* serveWithVite(
109109
// have a negative effect unlike production where final output size is relevant.
110110
{ sourcemap: true, jit: true },
111111
1,
112+
true,
112113
);
113114

114115
// Extract output index from options

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

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,12 @@ export interface JavaScriptTransformerOptions {
2828
export class JavaScriptTransformer {
2929
#workerPool: Piscina | undefined;
3030
#commonOptions: Required<JavaScriptTransformerOptions>;
31+
#pendingfileResults?: Map<string, Promise<Uint8Array>>;
3132

3233
constructor(
3334
options: JavaScriptTransformerOptions,
3435
readonly maxThreads: number,
36+
reuseResults?: boolean,
3537
) {
3638
// Extract options to ensure only the named options are serialized and sent to the worker
3739
const {
@@ -46,6 +48,11 @@ export class JavaScriptTransformer {
4648
advancedOptimizations,
4749
jit,
4850
};
51+
52+
// Currently only tracks pending file transform results
53+
if (reuseResults) {
54+
this.#pendingfileResults = new Map();
55+
}
4956
}
5057

5158
#ensureWorkerPool(): Piscina {
@@ -68,13 +75,21 @@ export class JavaScriptTransformer {
6875
* @returns A promise that resolves to a UTF-8 encoded Uint8Array containing the result.
6976
*/
7077
transformFile(filename: string, skipLinker?: boolean): Promise<Uint8Array> {
71-
// Always send the request to a worker. Files are almost always from node modules which means
72-
// they may need linking. The data is also not yet available to perform most transformation checks.
73-
return this.#ensureWorkerPool().run({
74-
filename,
75-
skipLinker,
76-
...this.#commonOptions,
77-
});
78+
const pendingKey = `${!!skipLinker}--${filename}`;
79+
let pending = this.#pendingfileResults?.get(pendingKey);
80+
if (pending === undefined) {
81+
// Always send the request to a worker. Files are almost always from node modules which means
82+
// they may need linking. The data is also not yet available to perform most transformation checks.
83+
pending = this.#ensureWorkerPool().run({
84+
filename,
85+
skipLinker,
86+
...this.#commonOptions,
87+
});
88+
89+
this.#pendingfileResults?.set(pendingKey, pending);
90+
}
91+
92+
return pending;
7893
}
7994

8095
/**
@@ -112,6 +127,8 @@ export class JavaScriptTransformer {
112127
* @returns A void promise that resolves when closing is complete.
113128
*/
114129
async close(): Promise<void> {
130+
this.#pendingfileResults?.clear();
131+
115132
if (this.#workerPool) {
116133
// Workaround piscina bug where a worker thread will be recreated after destroy to meet the minimum.
117134
this.#workerPool.options.minThreads = 0;

0 commit comments

Comments
 (0)