Skip to content

Commit 42e439f

Browse files
mattlewis92alan-agius4
authored andcommitted
fix(@angular-devkit/build-angular): fix budgets for any script with differential loading enabled
Fixes #19849
1 parent b5c309a commit 42e439f

File tree

2 files changed

+181
-4
lines changed

2 files changed

+181
-4
lines changed

packages/angular_devkit/build_angular/src/utils/bundle-calculator.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* Use of this source code is governed by an MIT-style license that can be
66
* found in the LICENSE file at https://angular.io/license
77
*/
8+
import { basename } from 'path';
89
import * as webpack from 'webpack';
910
import { Budget, Type } from '../browser/schema';
1011
import { ProcessBundleFile, ProcessBundleResult } from '../utils/process-bundle';
@@ -181,6 +182,18 @@ abstract class Calculator {
181182
.reduce((l, r) => l + r, 0);
182183
}
183184
}
185+
186+
protected getAssetSize(asset: Asset): number {
187+
if (asset.name.endsWith('.js')) {
188+
const processResult = this.processResults
189+
.find((processResult) => processResult.original && basename(processResult.original.filename) === asset.name);
190+
if (processResult?.original) {
191+
return processResult.original.size;
192+
}
193+
}
194+
195+
return asset.size;
196+
}
184197
}
185198

186199
/**
@@ -246,7 +259,7 @@ class AllScriptCalculator extends Calculator {
246259
calculate() {
247260
const size = this.assets
248261
.filter(asset => asset.name.endsWith('.js'))
249-
.map(asset => asset.size)
262+
.map(asset => this.getAssetSize(asset))
250263
.reduce((total: number, size: number) => total + size, 0);
251264

252265
return [{size, label: 'total scripts'}];
@@ -260,7 +273,7 @@ class AllCalculator extends Calculator {
260273
calculate() {
261274
const size = this.assets
262275
.filter(asset => !asset.name.endsWith('.map'))
263-
.map(asset => asset.size)
276+
.map(asset => this.getAssetSize(asset))
264277
.reduce((total: number, size: number) => total + size, 0);
265278

266279
return [{size, label: 'total'}];
@@ -275,7 +288,7 @@ class AnyScriptCalculator extends Calculator {
275288
return this.assets
276289
.filter(asset => asset.name.endsWith('.js'))
277290
.map(asset => ({
278-
size: asset.size,
291+
size: this.getAssetSize(asset),
279292
label: asset.name,
280293
}));
281294
}
@@ -289,7 +302,7 @@ class AnyCalculator extends Calculator {
289302
return this.assets
290303
.filter(asset => !asset.name.endsWith('.map'))
291304
.map(asset => ({
292-
size: asset.size,
305+
size: this.getAssetSize(asset),
293306
label: asset.name,
294307
}));
295308
}

packages/angular_devkit/build_angular/src/utils/bundle-calculator_spec.ts

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,5 +464,169 @@ describe('bundle-calculator', () => {
464464
message: jasmine.stringMatching('foo.ext exceeded maximum budget.'),
465465
});
466466
});
467+
468+
it('does *not* yield a combined differential bundle budget for any script', () => {
469+
const budgets: Budget[] = [{
470+
type: Type.AnyScript,
471+
maximumError: '1kb',
472+
}];
473+
const stats = {
474+
chunks: [
475+
{
476+
initial: true,
477+
files: [ 'foo.js' ],
478+
},
479+
],
480+
assets: [
481+
{
482+
name: 'main-es2015.js',
483+
size: 1.25 * KB,
484+
},
485+
],
486+
} as unknown as webpack.Stats.ToJsonOutput;
487+
const processResults: ProcessBundleResult[] = [
488+
{
489+
name: '0',
490+
// Individual builds are under budget, but combined they are over.
491+
original: {
492+
filename: '/home/main-es2015.js',
493+
size: 0.5 * KB,
494+
},
495+
downlevel: {
496+
filename: '/home/main-es5.js',
497+
size: 0.75 * KB,
498+
},
499+
},
500+
];
501+
502+
const failures = Array.from(checkBudgets(budgets, stats, processResults));
503+
504+
// Because individual builds are under budget, they are acceptable. Should
505+
// **not** yield a combined build which is over budget.
506+
expect(failures.length).toBe(0);
507+
});
508+
509+
it('does *not* yield a combined differential bundle budget for all script', () => {
510+
const budgets: Budget[] = [{
511+
type: Type.AllScript,
512+
maximumError: '1kb',
513+
}];
514+
const stats = {
515+
chunks: [
516+
{
517+
initial: true,
518+
files: [ 'foo.js' ],
519+
},
520+
],
521+
assets: [
522+
{
523+
name: 'main-es2015.js',
524+
size: 1.25 * KB,
525+
},
526+
],
527+
} as unknown as webpack.Stats.ToJsonOutput;
528+
const processResults: ProcessBundleResult[] = [
529+
{
530+
name: '0',
531+
// Individual builds are under budget, but combined they are over.
532+
original: {
533+
filename: '/home/main-es2015.js',
534+
size: 0.5 * KB,
535+
},
536+
downlevel: {
537+
filename: '/home/main-es5.js',
538+
size: 0.75 * KB,
539+
},
540+
},
541+
];
542+
543+
const failures = Array.from(checkBudgets(budgets, stats, processResults));
544+
545+
// Because individual builds are under budget, they are acceptable. Should
546+
// **not** yield a combined build which is over budget.
547+
expect(failures.length).toBe(0);
548+
});
549+
550+
it('does *not* yield a combined differential bundle budget for total budget', () => {
551+
const budgets: Budget[] = [{
552+
type: Type.All,
553+
maximumError: '1kb',
554+
}];
555+
const stats = {
556+
chunks: [
557+
{
558+
initial: true,
559+
files: [ 'foo.js' ],
560+
},
561+
],
562+
assets: [
563+
{
564+
name: 'main-es2015.js',
565+
size: 1.25 * KB,
566+
},
567+
],
568+
} as unknown as webpack.Stats.ToJsonOutput;
569+
const processResults: ProcessBundleResult[] = [
570+
{
571+
name: '0',
572+
// Individual builds are under budget, but combined they are over.
573+
original: {
574+
filename: '/home/main-es2015.js',
575+
size: 0.5 * KB,
576+
},
577+
downlevel: {
578+
filename: '/home/main-es5.js',
579+
size: 0.75 * KB,
580+
},
581+
},
582+
];
583+
584+
const failures = Array.from(checkBudgets(budgets, stats, processResults));
585+
586+
// Because individual builds are under budget, they are acceptable. Should
587+
// **not** yield a combined build which is over budget.
588+
expect(failures.length).toBe(0);
589+
});
590+
591+
it('does *not* yield a combined differential bundle budget for individual file budget', () => {
592+
const budgets: Budget[] = [{
593+
type: Type.Any,
594+
maximumError: '1kb',
595+
}];
596+
const stats = {
597+
chunks: [
598+
{
599+
initial: true,
600+
files: [ 'foo.js' ],
601+
},
602+
],
603+
assets: [
604+
{
605+
name: 'main-es2015.js',
606+
size: 1.25 * KB,
607+
},
608+
],
609+
} as unknown as webpack.Stats.ToJsonOutput;
610+
const processResults: ProcessBundleResult[] = [
611+
{
612+
name: '0',
613+
// Individual builds are under budget, but combined they are over.
614+
original: {
615+
filename: '/home/main-es2015.js',
616+
size: 0.5 * KB,
617+
},
618+
downlevel: {
619+
filename: '/home/main-es5.js',
620+
size: 0.75 * KB,
621+
},
622+
},
623+
];
624+
625+
const failures = Array.from(checkBudgets(budgets, stats, processResults));
626+
627+
// Because individual builds are under budget, they are acceptable. Should
628+
// **not** yield a combined build which is over budget.
629+
expect(failures.length).toBe(0);
630+
});
467631
});
468632
});

0 commit comments

Comments
 (0)