Skip to content

Commit 8321463

Browse files
clydindgp1130
authored andcommitted
perf(@angular-devkit/build-angular): reuse esbuild generated output file hashes
The development server used with the esbuild-based builders (`application`/`browser-esbuild`) will now use the recently introduced hash values provided by esbuild in its output files. This removes the need for each file to be hashed and analyzed on each rebuild during the development server update analysis.
1 parent 706483d commit 8321463

File tree

3 files changed

+39
-25
lines changed

3 files changed

+39
-25
lines changed

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

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,11 @@ import type { DevServerBuilderOutput } from './webpack-server';
3535
interface OutputFileRecord {
3636
contents: Uint8Array;
3737
size: number;
38-
hash?: Buffer;
38+
hash?: string;
3939
updated: boolean;
4040
servable: boolean;
4141
}
4242

43-
function hashContent(contents: BinaryLike): Buffer {
44-
// TODO: Consider xxhash
45-
return createHash('sha256').update(contents).digest();
46-
}
47-
4843
export async function* serveWithVite(
4944
serverOptions: NormalizedDevServerOptions,
5045
builderName: string,
@@ -306,27 +301,22 @@ function analyzeResultFiles(
306301
continue;
307302
}
308303

309-
let fileHash: Buffer | undefined;
310304
const existingRecord = generatedFiles.get(filePath);
311-
if (existingRecord && existingRecord.size === file.contents.byteLength) {
312-
// Only hash existing file when needed
313-
if (existingRecord.hash === undefined) {
314-
existingRecord.hash = hashContent(existingRecord.contents);
315-
}
316-
317-
// Compare against latest result output
318-
fileHash = hashContent(file.contents);
319-
if (fileHash.equals(existingRecord.hash)) {
320-
// Same file
321-
existingRecord.updated = false;
322-
continue;
323-
}
305+
if (
306+
existingRecord &&
307+
existingRecord.size === file.contents.byteLength &&
308+
existingRecord.hash === file.hash
309+
) {
310+
// Same file
311+
existingRecord.updated = false;
312+
continue;
324313
}
325314

315+
// New or updated file
326316
generatedFiles.set(filePath, {
327317
contents: file.contents,
328318
size: file.contents.byteLength,
329-
hash: fileHash,
319+
hash: file.hash,
330320
updated: true,
331321
servable:
332322
file.type === BuildOutputFileType.Browser || file.type === BuildOutputFileType.Media,

packages/angular_devkit/build_angular/src/tools/esbuild/bundler-context.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {
1717
context,
1818
} from 'esbuild';
1919
import { basename, dirname, extname, join, relative } from 'node:path';
20-
import { createOutputFileFromData, createOutputFileFromText } from './utils';
20+
import { convertOutputFile } from './utils';
2121

2222
export type BundleContextResult =
2323
| { errors: Message[]; warnings: Message[] }
@@ -231,9 +231,9 @@ export class BundlerContext {
231231
}
232232
}
233233

234-
const outputFiles = result.outputFiles.map(({ contents, path }) => {
234+
const outputFiles = result.outputFiles.map((file) => {
235235
let fileType: BuildOutputFileType;
236-
if (dirname(path) === 'media') {
236+
if (dirname(file.path) === 'media') {
237237
fileType = BuildOutputFileType.Media;
238238
} else {
239239
fileType =
@@ -242,7 +242,7 @@ export class BundlerContext {
242242
: BuildOutputFileType.Browser;
243243
}
244244

245-
return createOutputFileFromData(path, contents, fileType);
245+
return convertOutputFile(file, fileType);
246246
});
247247

248248
// Return the successful build results

packages/angular_devkit/build_angular/src/tools/esbuild/utils.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,30 @@ export function createOutputFileFromData(
281281
};
282282
}
283283

284+
export function convertOutputFile(file: OutputFile, type: BuildOutputFileType): BuildOutputFile {
285+
const { path, contents, hash } = file;
286+
287+
return {
288+
contents,
289+
hash,
290+
path,
291+
type,
292+
get text() {
293+
return Buffer.from(
294+
this.contents.buffer,
295+
this.contents.byteOffset,
296+
this.contents.byteLength,
297+
).toString('utf-8');
298+
},
299+
get fullOutputPath(): string {
300+
return getFullOutputPath(this);
301+
},
302+
clone(): BuildOutputFile {
303+
return convertOutputFile(this, this.type);
304+
},
305+
};
306+
}
307+
284308
export function getFullOutputPath(file: BuildOutputFile): string {
285309
switch (file.type) {
286310
case BuildOutputFileType.Browser:

0 commit comments

Comments
 (0)