Skip to content

Commit 3affd28

Browse files
clydinalan-agius4
authored andcommitted
perf(@angular-devkit/build-angular): remove Webpack Stats.toJson usage in analytics plugin
Webpack's Stats.toJson function is an expensive operation and is recommended to be avoided where possible. In the case of the analytics plugin, the chunks and assets can be accessed directly from the Webpack compilation.
1 parent dfefd6b commit 3affd28

File tree

1 file changed

+22
-19
lines changed
  • packages/angular_devkit/build_angular/src/webpack/plugins

1 file changed

+22
-19
lines changed

packages/angular_devkit/build_angular/src/webpack/plugins/analytics.ts

+22-19
Original file line numberDiff line numberDiff line change
@@ -196,16 +196,17 @@ export class NgBuildAnalyticsPlugin {
196196
}
197197
}
198198

199-
// We can safely disable no any here since we know the format of the JSON output from webpack.
200-
// tslint:disable-next-line:no-any
201-
protected _collectBundleStats(json: any) {
202-
json.chunks
199+
protected _collectBundleStats(compilation: compilation.Compilation) {
200+
// `compilation.chunks` is a Set in Webpack 5
201+
const chunks = Array.from(compilation.chunks);
202+
203+
chunks
203204
.filter((chunk: { rendered?: boolean }) => chunk.rendered)
204-
.forEach((chunk: { files: string[], initial?: boolean, entry?: boolean }) => {
205-
const asset = json.assets.find((x: { name: string }) => x.name == chunk.files[0]);
206-
const size = asset ? asset.size : 0;
205+
.forEach((chunk: { files: string[]; canBeInitial(): boolean }) => {
206+
const asset = compilation.assets[chunk.files[0]];
207+
const size = asset ? asset.size() : 0;
207208

208-
if (chunk.entry || chunk.initial) {
209+
if (chunk.canBeInitial()) {
209210
this._stats.initialChunkSize += size;
210211
} else {
211212
this._stats.lazyChunkCount++;
@@ -215,24 +216,26 @@ export class NgBuildAnalyticsPlugin {
215216
this._stats.totalChunkSize += size;
216217
});
217218

218-
json.assets
219+
Object.entries<{ size(): number }>(compilation.assets)
219220
// Filter out chunks. We only count assets that are not JS.
220-
.filter((a: { name: string }) => {
221-
return json.chunks.every((chunk: { files: string[] }) => chunk.files[0] != a.name);
221+
.filter(([name]) => {
222+
return chunks.every((chunk: { files: string[] }) => chunk.files[0] != name);
222223
})
223-
.forEach((a: { size?: number }) => {
224-
this._stats.assetSize += (a.size || 0);
224+
.forEach(([, asset]) => {
225+
this._stats.assetSize += asset.size();
225226
this._stats.assetCount++;
226227
});
227228

228-
for (const asset of json.assets) {
229-
if (asset.name == 'polyfill') {
230-
this._stats.polyfillSize += asset.size || 0;
229+
for (const [name, asset] of Object.entries<{ size(): number }>(compilation.assets)) {
230+
if (name == 'polyfill') {
231+
this._stats.polyfillSize += asset.size();
231232
}
232233
}
233-
for (const chunk of json.chunks) {
234+
for (const chunk of compilation.chunks) {
234235
if (chunk.files[0] && chunk.files[0].endsWith('.css')) {
235-
this._stats.cssSize += chunk.size || 0;
236+
const asset = compilation.assets[chunk.files[0]];
237+
const size = asset ? asset.size() : 0;
238+
this._stats.cssSize += size;
236239
}
237240
}
238241
}
@@ -276,7 +279,7 @@ export class NgBuildAnalyticsPlugin {
276279

277280
protected _done(stats: Stats) {
278281
this._collectErrors(stats);
279-
this._collectBundleStats(stats.toJson());
282+
this._collectBundleStats(stats.compilation);
280283
if (this._built) {
281284
this._reportRebuildMetrics(stats);
282285
} else {

0 commit comments

Comments
 (0)