Skip to content

Commit 4e0743c

Browse files
alan-agius4clydin
authored andcommitted
perf(@angular-devkit/build-angular): change webpack hashing function to xxhash64
`xxhash64` uses a faster WASM based hash mechanism.
1 parent 55be137 commit 4e0743c

File tree

9 files changed

+42
-42
lines changed

9 files changed

+42
-42
lines changed

packages/angular_devkit/build_angular/src/builders/app-shell/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ async function _getServerModuleBundlePath(
143143
throw new Error(`Could not find server output directory: ${outputPath}.`);
144144
}
145145

146-
const re = /^main\.(?:[a-zA-Z0-9]{20}\.)?js$/;
146+
const re = /^main\.(?:[a-zA-Z0-9]{16}\.)?js$/;
147147
const maybeMain = fs.readdirSync(outputPath).find((x) => re.test(x));
148148

149149
if (!maybeMain) {

packages/angular_devkit/build_angular/src/builders/browser/specs/source-map_spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ describe('Browser Builder source map', () => {
5858
outputHashing: OutputHashing.All,
5959
});
6060

61-
expect(Object.keys(files).some((name) => /main\.[0-9a-f]{20}\.js.map/.test(name))).toBeTruthy();
61+
expect(Object.keys(files).some((name) => /main\.[0-9a-f]{16}\.js.map/.test(name))).toBeTruthy();
6262
});
6363

6464
it('does not output source map when disabled', async () => {

packages/angular_devkit/build_angular/src/builders/browser/specs/web-worker_spec.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ describe('Browser Builder Web Worker support', () => {
120120
// Worker bundle should have hash and minified code.
121121
const workerBundle = host.fileMatchExists(
122122
outputPath,
123-
/src_app_app_worker_ts\.[0-9a-f]{20}\.js/,
123+
/src_app_app_worker_ts\.[0-9a-f]{16}\.js/,
124124
) as string;
125125
expect(workerBundle).toBeTruthy('workerBundle should exist');
126126
const workerContent = virtualFs.fileBufferToString(
@@ -131,7 +131,7 @@ describe('Browser Builder Web Worker support', () => {
131131
expect(workerContent).toContain('"hello"===e&&postMessage');
132132

133133
// Main bundle should reference hashed worker bundle.
134-
const mainBundle = host.fileMatchExists(outputPath, /main\.[0-9a-f]{20}\.js/) as string;
134+
const mainBundle = host.fileMatchExists(outputPath, /main\.[0-9a-f]{16}\.js/) as string;
135135
expect(mainBundle).toBeTruthy('mainBundle should exist');
136136
const mainContent = virtualFs.fileBufferToString(
137137
host.scopedSync().read(join(outputPath, mainBundle)),

packages/angular_devkit/build_angular/src/builders/browser/tests/options/output-hashing_spec.ts

+25-25
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ describeBuilder(buildWebpackBrowser, BROWSER_BUILDER_INFO, (harness) => {
3131
const { result } = await harness.executeOnce();
3232
expect(result?.success).toBe(true);
3333

34-
expect(harness.hasFileMatch('dist', /runtime\.[0-9a-f]{20}\.js$/)).toBeTrue();
35-
expect(harness.hasFileMatch('dist', /main\.[0-9a-f]{20}\.js$/)).toBeTrue();
36-
expect(harness.hasFileMatch('dist', /polyfills\.[0-9a-f]{20}\.js$/)).toBeTrue();
37-
expect(harness.hasFileMatch('dist', /styles\.[0-9a-f]{20}\.css$/)).toBeTrue();
34+
expect(harness.hasFileMatch('dist', /runtime\.[0-9a-f]{16}\.js$/)).toBeTrue();
35+
expect(harness.hasFileMatch('dist', /main\.[0-9a-f]{16}\.js$/)).toBeTrue();
36+
expect(harness.hasFileMatch('dist', /polyfills\.[0-9a-f]{16}\.js$/)).toBeTrue();
37+
expect(harness.hasFileMatch('dist', /styles\.[0-9a-f]{16}\.css$/)).toBeTrue();
3838
expect(harness.hasFileMatch('dist', /spectrum\.[0-9a-f]{20}\.png$/)).toBeTrue();
3939
});
4040

@@ -50,11 +50,11 @@ describeBuilder(buildWebpackBrowser, BROWSER_BUILDER_INFO, (harness) => {
5050
const { result } = await harness.executeOnce();
5151
expect(result?.success).toBe(true);
5252

53-
expect(harness.hasFileMatch('dist', /runtime\.[0-9a-f]{20}\.js$/)).toBeFalse();
54-
expect(harness.hasFileMatch('dist', /main\.[0-9a-f]{20}\.js$/)).toBeFalse();
55-
expect(harness.hasFileMatch('dist', /polyfills\.[0-9a-f]{20}\.js$/)).toBeFalse();
56-
expect(harness.hasFileMatch('dist', /styles\.[0-9a-f]{20}\.css$/)).toBeFalse();
57-
expect(harness.hasFileMatch('dist', /spectrum\.[0-9a-f]{20}\.png$/)).toBeFalse();
53+
expect(harness.hasFileMatch('dist', /runtime\.[0-9a-f]{16}\.js$/)).toBeFalse();
54+
expect(harness.hasFileMatch('dist', /main\.[0-9a-f]{16}\.js$/)).toBeFalse();
55+
expect(harness.hasFileMatch('dist', /polyfills\.[0-9a-f]{16}\.js$/)).toBeFalse();
56+
expect(harness.hasFileMatch('dist', /styles\.[0-9a-f]{16}\.css$/)).toBeFalse();
57+
expect(harness.hasFileMatch('dist', /spectrum\.[0-9a-f]{16}\.png$/)).toBeFalse();
5858
});
5959

6060
it(`doesn't hash any filenames when set to "none"`, async () => {
@@ -70,11 +70,11 @@ describeBuilder(buildWebpackBrowser, BROWSER_BUILDER_INFO, (harness) => {
7070
const { result } = await harness.executeOnce();
7171
expect(result?.success).toBe(true);
7272

73-
expect(harness.hasFileMatch('dist', /runtime\.[0-9a-f]{20}\.js$/)).toBeFalse();
74-
expect(harness.hasFileMatch('dist', /main\.[0-9a-f]{20}\.js$/)).toBeFalse();
75-
expect(harness.hasFileMatch('dist', /polyfills\.[0-9a-f]{20}\.js$/)).toBeFalse();
76-
expect(harness.hasFileMatch('dist', /styles\.[0-9a-f]{20}\.css$/)).toBeFalse();
77-
expect(harness.hasFileMatch('dist', /spectrum\.[0-9a-f]{20}\.png$/)).toBeFalse();
73+
expect(harness.hasFileMatch('dist', /runtime\.[0-9a-f]{16}\.js$/)).toBeFalse();
74+
expect(harness.hasFileMatch('dist', /main\.[0-9a-f]{16}\.js$/)).toBeFalse();
75+
expect(harness.hasFileMatch('dist', /polyfills\.[0-9a-f]{16}\.js$/)).toBeFalse();
76+
expect(harness.hasFileMatch('dist', /styles\.[0-9a-f]{16}\.css$/)).toBeFalse();
77+
expect(harness.hasFileMatch('dist', /spectrum\.[0-9a-f]{16}\.png$/)).toBeFalse();
7878
});
7979

8080
it(`hashes CSS resources filenames only when set to "media"`, async () => {
@@ -90,10 +90,10 @@ describeBuilder(buildWebpackBrowser, BROWSER_BUILDER_INFO, (harness) => {
9090
const { result } = await harness.executeOnce();
9191
expect(result?.success).toBe(true);
9292

93-
expect(harness.hasFileMatch('dist', /runtime\.[0-9a-f]{20}\.js$/)).toBeFalse();
94-
expect(harness.hasFileMatch('dist', /main\.[0-9a-f]{20}\.js$/)).toBeFalse();
95-
expect(harness.hasFileMatch('dist', /polyfills\.[0-9a-f]{20}\.js$/)).toBeFalse();
96-
expect(harness.hasFileMatch('dist', /styles\.[0-9a-f]{20}\.css$/)).toBeFalse();
93+
expect(harness.hasFileMatch('dist', /runtime\.[0-9a-f]{16}\.js$/)).toBeFalse();
94+
expect(harness.hasFileMatch('dist', /main\.[0-9a-f]{16}\.js$/)).toBeFalse();
95+
expect(harness.hasFileMatch('dist', /polyfills\.[0-9a-f]{16}\.js$/)).toBeFalse();
96+
expect(harness.hasFileMatch('dist', /styles\.[0-9a-f]{16}\.css$/)).toBeFalse();
9797
expect(harness.hasFileMatch('dist', /spectrum\.[0-9a-f]{20}\.png$/)).toBeTrue();
9898
});
9999

@@ -110,11 +110,11 @@ describeBuilder(buildWebpackBrowser, BROWSER_BUILDER_INFO, (harness) => {
110110
const { result } = await harness.executeOnce();
111111
expect(result?.success).toBe(true);
112112

113-
expect(harness.hasFileMatch('dist', /runtime\.[0-9a-f]{20}\.js$/)).toBeTrue();
114-
expect(harness.hasFileMatch('dist', /main\.[0-9a-f]{20}\.js$/)).toBeTrue();
115-
expect(harness.hasFileMatch('dist', /polyfills\.[0-9a-f]{20}\.js$/)).toBeTrue();
116-
expect(harness.hasFileMatch('dist', /styles\.[0-9a-f]{20}\.css$/)).toBeTrue();
117-
expect(harness.hasFileMatch('dist', /spectrum\.[0-9a-f]{20}\.png$/)).toBeFalse();
113+
expect(harness.hasFileMatch('dist', /runtime\.[0-9a-f]{16}\.js$/)).toBeTrue();
114+
expect(harness.hasFileMatch('dist', /main\.[0-9a-f]{16}\.js$/)).toBeTrue();
115+
expect(harness.hasFileMatch('dist', /polyfills\.[0-9a-f]{16}\.js$/)).toBeTrue();
116+
expect(harness.hasFileMatch('dist', /styles\.[0-9a-f]{16}\.css$/)).toBeTrue();
117+
expect(harness.hasFileMatch('dist', /spectrum\.[0-9a-f]{16}\.png$/)).toBeFalse();
118118
});
119119

120120
it('does not hash non injected styles', async () => {
@@ -133,8 +133,8 @@ describeBuilder(buildWebpackBrowser, BROWSER_BUILDER_INFO, (harness) => {
133133
const { result } = await harness.executeOnce();
134134
expect(result?.success).toBe(true);
135135

136-
expect(harness.hasFileMatch('dist', /styles\.[0-9a-f]{20}\.js$/)).toBeFalse();
137-
expect(harness.hasFileMatch('dist', /styles\.[0-9a-f]{20}\.js.map$/)).toBeFalse();
136+
expect(harness.hasFileMatch('dist', /styles\.[0-9a-f]{16}\.js$/)).toBeFalse();
137+
expect(harness.hasFileMatch('dist', /styles\.[0-9a-f]{16}\.js.map$/)).toBeFalse();
138138
harness.expectFile('dist/styles.css').toExist();
139139
harness.expectFile('dist/styles.css.map').toExist();
140140
});

packages/angular_devkit/build_angular/src/webpack/configs/common.ts

+1
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,7 @@ export async function getCommonConfig(wco: WebpackConfigOptions): Promise<Config
342342
context: root,
343343
entry: entryPoints,
344344
output: {
345+
hashFunction: 'xxhash64', // todo: remove in webpack 6. This is part of `futureDefaults`.
345346
clean: buildOptions.deleteOutputPath ?? true,
346347
path: path.resolve(root, buildOptions.outputPath),
347348
publicPath: buildOptions.deployUrl ?? '',

tests/legacy-cli/e2e/tests/basic/build.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export default async function () {
1313

1414
// Production build
1515
const { stderr: stderrProgress, stdout } = await ng('build', '--progress');
16-
await expectFileToMatch('dist/test-project/index.html', /main\.[a-zA-Z0-9]{20}\.js/);
16+
await expectFileToMatch('dist/test-project/index.html', /main\.[a-zA-Z0-9]{16}\.js/);
1717

1818
if (!stdout.includes('Initial Total')) {
1919
throw new Error(`Expected stdout to contain 'Initial Total' but it did not.\n${stdout}`);

tests/legacy-cli/e2e/tests/build/output-hashing.ts

+8-9
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { copyProjectAsset } from '../../utils/assets';
22
import { expectFileMatchToExist, expectFileToMatch, writeMultipleFiles } from '../../utils/fs';
33
import { ng } from '../../utils/process';
44

5-
65
async function verifyMedia(fileNameRe: RegExp, content: RegExp) {
76
const fileName = await expectFileMatchToExist('dist/test-project/', fileNameRe);
87
await expectFileToMatch(`dist/test-project/${fileName}`, content);
@@ -15,10 +14,10 @@ export default async function () {
1514
// use image with file size >10KB to prevent inlining
1615
await copyProjectAsset('images/spectrum.png', './src/assets/image.png');
1716
await ng('build', '--output-hashing=all', '--configuration=development');
18-
await expectFileToMatch('dist/test-project/index.html', /runtime\.[0-9a-f]{20}\.js/);
19-
await expectFileToMatch('dist/test-project/index.html', /main\.[0-9a-f]{20}\.js/);
20-
await expectFileToMatch('dist/test-project/index.html', /styles\.[0-9a-f]{20}\.(css|js)/);
21-
await verifyMedia(/styles\.[0-9a-f]{20}\.(css|js)/, /image\.[0-9a-f]{20}\.png/);
17+
await expectFileToMatch('dist/test-project/index.html', /runtime\.[0-9a-f]{16}\.js/);
18+
await expectFileToMatch('dist/test-project/index.html', /main\.[0-9a-f]{16}\.js/);
19+
await expectFileToMatch('dist/test-project/index.html', /styles\.[0-9a-f]{16}\.(css|js)/);
20+
await verifyMedia(/styles\.[0-9a-f]{16}\.(css|js)/, /image\.[0-9a-f]{20}\.png/);
2221

2322
await ng('build', '--output-hashing=none', '--configuration=development');
2423
await expectFileToMatch('dist/test-project/index.html', /runtime\.js/);
@@ -33,8 +32,8 @@ export default async function () {
3332
await verifyMedia(/styles\.(css|js)/, /image\.[0-9a-f]{20}\.png/);
3433

3534
await ng('build', '--output-hashing=bundles', '--configuration=development');
36-
await expectFileToMatch('dist/test-project/index.html', /runtime\.[0-9a-f]{20}\.js/);
37-
await expectFileToMatch('dist/test-project/index.html', /main\.[0-9a-f]{20}\.js/);
38-
await expectFileToMatch('dist/test-project/index.html', /styles\.[0-9a-f]{20}\.(css|js)/);
39-
await verifyMedia(/styles\.[0-9a-f]{20}\.(css|js)/, /image\.png/);
35+
await expectFileToMatch('dist/test-project/index.html', /runtime\.[0-9a-f]{16}\.js/);
36+
await expectFileToMatch('dist/test-project/index.html', /main\.[0-9a-f]{16}\.js/);
37+
await expectFileToMatch('dist/test-project/index.html', /styles\.[0-9a-f]{16}\.(css|js)/);
38+
await verifyMedia(/styles\.[0-9a-f]{16}\.(css|js)/, /image\.png/);
4039
}

tests/legacy-cli/e2e/tests/build/prod-build.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ export default async function () {
3232
await ng('build');
3333
await expectFileToExist(join(process.cwd(), 'dist'));
3434
// Check for cache busting hash script src
35-
await expectFileToMatch('dist/test-project/index.html', /main\.[0-9a-f]{20}\.js/);
36-
await expectFileToMatch('dist/test-project/index.html', /styles\.[0-9a-f]{20}\.css/);
35+
await expectFileToMatch('dist/test-project/index.html', /main\.[0-9a-f]{16}\.js/);
36+
await expectFileToMatch('dist/test-project/index.html', /styles\.[0-9a-f]{16}\.css/);
3737
await expectFileToMatch('dist/test-project/3rdpartylicenses.txt', /MIT/);
3838

3939
const indexContent = await readFile('dist/test-project/index.html');

tests/legacy-cli/e2e/tests/update/update-9.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,5 +50,5 @@ export default async function () {
5050

5151
// Verify project now creates bundles
5252
await noSilentNg('build', '--prod');
53-
await expectFileMatchToExist('dist/nine-project/', /main\.[0-9a-f]{20}\.js/);
53+
await expectFileMatchToExist('dist/nine-project/', /main\.[0-9a-f]{16}\.js/);
5454
}

0 commit comments

Comments
 (0)