Skip to content

Commit 0441015

Browse files
committed
perf(@ngtools/webpack): use Webpack's built-in xxhash64 support
Webpack provides built-in support for creating hashes using the xxhash64 algorithm via a WebAssembly module. This can be significantly faster than the previously used md5 algorithm. The Webpack peer dependency has also been update to a minimum of 5.54.0 to ensure xxhash64 supported is available.
1 parent 94288c7 commit 0441015

File tree

3 files changed

+20
-7
lines changed

3 files changed

+20
-7
lines changed

packages/ngtools/webpack/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
"peerDependencies": {
2525
"@angular/compiler-cli": "^14.0.0 || ^14.0.0-next",
2626
"typescript": "~4.6.2",
27-
"webpack": "^5.30.0"
27+
"webpack": "^5.54.0"
2828
},
2929
"devDependencies": {
3030
"@angular-devkit/core": "0.0.0-PLACEHOLDER",

packages/ngtools/webpack/src/ivy/plugin.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
import type { CompilerHost, CompilerOptions, NgtscProgram } from '@angular/compiler-cli';
1010
import { strict as assert } from 'assert';
11-
import { createHash } from 'crypto';
1211
import * as ts from 'typescript';
1312
import type { Compilation, Compiler, Module, NormalModule } from 'webpack';
1413
import { NgccProcessor } from '../ngcc_processor';
@@ -107,6 +106,7 @@ export class AngularWebpackPlugin {
107106
private builder?: ts.EmitAndSemanticDiagnosticsBuilderProgram;
108107
private sourceFileCache?: SourceFileCache;
109108
private webpackCache?: ReturnType<Compilation['getCache']>;
109+
private webpackCreateHash?: Compiler['webpack']['util']['createHash'];
110110
private readonly fileDependencies = new Map<string, Set<string>>();
111111
private readonly requiredFilesToEmit = new Set<string>();
112112
private readonly requiredFilesToEmitCache = new Map<string, EmitFileResult | undefined>();
@@ -141,6 +141,7 @@ export class AngularWebpackPlugin {
141141
// eslint-disable-next-line max-lines-per-function
142142
apply(compiler: Compiler): void {
143143
const { NormalModuleReplacementPlugin, util } = compiler.webpack;
144+
this.webpackCreateHash = util.createHash;
144145

145146
// Setup file replacements with webpack
146147
for (const [key, value] of Object.entries(this.pluginOptions.fileReplacements)) {
@@ -745,9 +746,11 @@ export class AngularWebpackPlugin {
745746
filePath: string,
746747
content: string,
747748
): Promise<FileEmitHistoryItem> {
749+
assert.ok(this.webpackCreateHash, 'File emitter is used prior to Webpack compilation');
750+
748751
const historyData: FileEmitHistoryItem = {
749752
length: content.length,
750-
hash: createHash('md5').update(content).digest(),
753+
hash: this.webpackCreateHash('xxhash64').update(content).digest() as Uint8Array,
751754
};
752755

753756
if (this.webpackCache) {

packages/ngtools/webpack/src/resource_loader.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import { createHash } from 'crypto';
109
import * as path from 'path';
1110
import * as vm from 'vm';
1211
import type { Asset, Compilation } from 'webpack';
@@ -100,6 +99,7 @@ export class WebpackResourceLoader {
10099
this._reverseDependencies.set(file, new Set(resources));
101100
}
102101

102+
// eslint-disable-next-line max-lines-per-function
103103
private async _compile(
104104
filePath?: string,
105105
data?: string,
@@ -111,6 +111,16 @@ export class WebpackResourceLoader {
111111
throw new Error('WebpackResourceLoader cannot be used without parentCompilation');
112112
}
113113

114+
const { context, webpack } = this._parentCompilation.compiler;
115+
const {
116+
EntryPlugin,
117+
NormalModule,
118+
library,
119+
node,
120+
sources,
121+
util: { createHash },
122+
} = webpack;
123+
114124
const getEntry = (): string => {
115125
if (filePath) {
116126
return `${filePath}?${NG_COMPONENT_RESOURCE_QUERY}`;
@@ -122,7 +132,9 @@ export class WebpackResourceLoader {
122132
);
123133
} else if (data) {
124134
// Create a special URL for reading the resource from memory
125-
return `angular-resource:${resourceType},${createHash('md5').update(data).digest('hex')}`;
135+
return `angular-resource:${resourceType},${createHash('xxhash64')
136+
.update(data)
137+
.digest('hex')}`;
126138
}
127139

128140
throw new Error(`"filePath", "resourceType" or "data" must be specified.`);
@@ -150,8 +162,6 @@ export class WebpackResourceLoader {
150162
},
151163
};
152164

153-
const { context, webpack } = this._parentCompilation.compiler;
154-
const { EntryPlugin, NormalModule, library, node, sources } = webpack;
155165
const childCompiler = this._parentCompilation.createChildCompiler(
156166
'angular-compiler:resource',
157167
outputOptions,

0 commit comments

Comments
 (0)