Skip to content

Commit 4d27c38

Browse files
committed
refactor(@angular-devkit/build-angular): reduce Webpack specific overlap in bundle budget calculator
Webpack-specific types and imports have been reduced within the logic and test code for the bundle budget calculator. This reduces the amount of unused code that needs to be loaded when not using a Webpack-based bundler. The Webpack component style budget plugin was also updated to use only the `checkBudgets` function instead of the previous two function setup which limits the needed amount of runtime exports for the plugin.
1 parent 7549f1b commit 4d27c38

File tree

3 files changed

+64
-64
lines changed

3 files changed

+64
-64
lines changed

packages/angular_devkit/build_angular/src/tools/webpack/plugins/any-component-style-budget-checker.ts

+24-25
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@
88

99
import * as path from 'path';
1010
import { Compilation, Compiler } from 'webpack';
11-
import { Budget, Type } from '../../../builders/browser/schema';
1211
import {
12+
BudgetAsset,
13+
BudgetEntry,
14+
BudgetType,
1315
ThresholdSeverity,
14-
calculateThresholds,
15-
checkThresholds,
16+
checkBudgets,
1617
} from '../../../utils/bundle-calculator';
1718
import { addError, addWarning } from '../../../utils/webpack-diagnostics';
1819

@@ -23,10 +24,10 @@ const PLUGIN_NAME = 'AnyComponentStyleBudgetChecker';
2324
* budget is exceeded by a particular component's styles.
2425
*/
2526
export class AnyComponentStyleBudgetChecker {
26-
private readonly budgets: Budget[];
27+
private readonly budgets: BudgetEntry[];
2728

28-
constructor(budgets: Budget[]) {
29-
this.budgets = budgets.filter((budget) => budget.type === Type.AnyComponentStyle);
29+
constructor(budgets: BudgetEntry[]) {
30+
this.budgets = budgets.filter((budget) => budget.type === BudgetType.AnyComponentStyle);
3031
}
3132

3233
apply(compiler: Compiler) {
@@ -49,30 +50,28 @@ export class AnyComponentStyleBudgetChecker {
4950

5051
const cssExtensions = ['.css', '.scss', '.less', '.sass'];
5152

52-
const componentStyles = Object.keys(compilation.assets)
53+
const componentStyles: BudgetAsset[] = Object.keys(compilation.assets)
5354
.filter((name) => cssExtensions.includes(path.extname(name)))
5455
.map((name) => ({
56+
name,
5557
size: compilation.assets[name].size(),
56-
label: name,
58+
componentStyle: true,
5759
}));
5860

59-
const thresholds = this.budgets.flatMap((budget) => [...calculateThresholds(budget)]);
60-
for (const { size, label } of componentStyles) {
61-
for (const { severity, message } of checkThresholds(
62-
thresholds[Symbol.iterator](),
63-
size,
64-
label,
65-
)) {
66-
switch (severity) {
67-
case ThresholdSeverity.Warning:
68-
addWarning(compilation, message);
69-
break;
70-
case ThresholdSeverity.Error:
71-
addError(compilation, message);
72-
break;
73-
default:
74-
assertNever(severity);
75-
}
61+
for (const { severity, message } of checkBudgets(
62+
this.budgets,
63+
{ chunks: [], assets: componentStyles },
64+
true,
65+
)) {
66+
switch (severity) {
67+
case ThresholdSeverity.Warning:
68+
addWarning(compilation, message);
69+
break;
70+
case ThresholdSeverity.Error:
71+
addError(compilation, message);
72+
break;
73+
default:
74+
assertNever(severity);
7675
}
7776
}
7877
},

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

+12-9
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,12 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import { Budget, Type } from '../builders/browser/schema';
9+
import { Budget as BudgetEntry, Type as BudgetType } from '../builders/application/schema';
1010
import { formatSize } from './format-bytes';
1111

12+
// Re-export to avoid direct schema importing throughout code
13+
export { BudgetEntry, BudgetType };
14+
1215
interface Size {
1316
size: number;
1417
label?: string;
@@ -53,7 +56,7 @@ export interface BudgetStats {
5356
assets?: BudgetAsset[];
5457
}
5558

56-
export function* calculateThresholds(budget: Budget): IterableIterator<Threshold> {
59+
export function* calculateThresholds(budget: BudgetEntry): IterableIterator<Threshold> {
5760
if (budget.maximumWarning) {
5861
yield {
5962
limit: calculateBytes(budget.maximumWarning, budget.baseline, 1),
@@ -118,11 +121,11 @@ export function* calculateThresholds(budget: Budget): IterableIterator<Threshold
118121
/**
119122
* Calculates the sizes for bundles in the budget type provided.
120123
*/
121-
function calculateSizes(budget: Budget, stats: BudgetStats): Size[] {
124+
function calculateSizes(budget: BudgetEntry, stats: BudgetStats): Size[] {
122125
type CalculatorTypes = {
123-
new (budget: Budget, chunks: BudgetChunk[], assets: BudgetAsset[]): Calculator;
126+
new (budget: BudgetEntry, chunks: BudgetChunk[], assets: BudgetAsset[]): Calculator;
124127
};
125-
const calculatorMap: Record<Budget['type'], CalculatorTypes> = {
128+
const calculatorMap: Record<BudgetType, CalculatorTypes> = {
126129
all: AllCalculator,
127130
allScript: AllScriptCalculator,
128131
any: AnyCalculator,
@@ -148,7 +151,7 @@ function calculateSizes(budget: Budget, stats: BudgetStats): Size[] {
148151

149152
abstract class Calculator {
150153
constructor(
151-
protected budget: Budget,
154+
protected budget: BudgetEntry,
152155
protected chunks: BudgetChunk[],
153156
protected assets: BudgetAsset[],
154157
) {}
@@ -321,14 +324,14 @@ function calculateBytes(input: string, baseline?: string, factor: 1 | -1 = 1): n
321324
}
322325

323326
export function* checkBudgets(
324-
budgets: Budget[],
327+
budgets: BudgetEntry[],
325328
stats: BudgetStats,
326329
checkComponentStyles?: boolean,
327330
): IterableIterator<BudgetCalculatorResult> {
328331
// Ignore AnyComponentStyle budgets as these are handled in `AnyComponentStyleBudgetChecker` unless requested
329332
const computableBudgets = checkComponentStyles
330333
? budgets
331-
: budgets.filter((budget) => budget.type !== Type.AnyComponentStyle);
334+
: budgets.filter((budget) => budget.type !== BudgetType.AnyComponentStyle);
332335

333336
for (const budget of computableBudgets) {
334337
const sizes = calculateSizes(budget, stats);
@@ -339,7 +342,7 @@ export function* checkBudgets(
339342
}
340343

341344
export function* checkThresholds(
342-
thresholds: IterableIterator<Threshold>,
345+
thresholds: Iterable<Threshold>,
343346
size: number,
344347
label?: string,
345348
): IterableIterator<BudgetCalculatorResult> {

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

+28-30
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,16 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import { StatsCompilation } from 'webpack';
10-
import { Budget, Type } from '../builders/browser/schema';
11-
import { ThresholdSeverity, checkBudgets } from './bundle-calculator';
9+
import { BudgetEntry, BudgetType, ThresholdSeverity, checkBudgets } from './bundle-calculator';
1210

1311
const KB = 1024;
1412

1513
describe('bundle-calculator', () => {
1614
describe('checkBudgets()', () => {
1715
it('yields maximum budgets exceeded', () => {
18-
const budgets: Budget[] = [
16+
const budgets: BudgetEntry[] = [
1917
{
20-
type: Type.Any,
18+
type: BudgetType.Any,
2119
maximumError: '1kb',
2220
},
2321
];
@@ -33,7 +31,7 @@ describe('bundle-calculator', () => {
3331
size: 0.5 * KB,
3432
},
3533
],
36-
} as unknown as StatsCompilation;
34+
};
3735

3836
const failures = Array.from(checkBudgets(budgets, stats));
3937

@@ -46,9 +44,9 @@ describe('bundle-calculator', () => {
4644
});
4745

4846
it('yields minimum budgets exceeded', () => {
49-
const budgets: Budget[] = [
47+
const budgets: BudgetEntry[] = [
5048
{
51-
type: Type.Any,
49+
type: BudgetType.Any,
5250
minimumError: '1kb',
5351
},
5452
];
@@ -64,7 +62,7 @@ describe('bundle-calculator', () => {
6462
size: 0.5 * KB,
6563
},
6664
],
67-
} as unknown as StatsCompilation;
65+
};
6866

6967
const failures = Array.from(checkBudgets(budgets, stats));
7068

@@ -77,9 +75,9 @@ describe('bundle-calculator', () => {
7775
});
7876

7977
it('yields exceeded bundle budgets', () => {
80-
const budgets: Budget[] = [
78+
const budgets: BudgetEntry[] = [
8179
{
82-
type: Type.Bundle,
80+
type: BudgetType.Bundle,
8381
name: 'foo',
8482
maximumError: '1kb',
8583
},
@@ -102,7 +100,7 @@ describe('bundle-calculator', () => {
102100
size: 0.75 * KB,
103101
},
104102
],
105-
} as unknown as StatsCompilation;
103+
};
106104

107105
const failures = Array.from(checkBudgets(budgets, stats));
108106

@@ -115,9 +113,9 @@ describe('bundle-calculator', () => {
115113
});
116114

117115
it('yields exceeded initial budget', () => {
118-
const budgets: Budget[] = [
116+
const budgets: BudgetEntry[] = [
119117
{
120-
type: Type.Initial,
118+
type: BudgetType.Initial,
121119
maximumError: '1kb',
122120
},
123121
];
@@ -140,7 +138,7 @@ describe('bundle-calculator', () => {
140138
size: 0.75 * KB,
141139
},
142140
],
143-
} as unknown as StatsCompilation;
141+
};
144142

145143
const failures = Array.from(checkBudgets(budgets, stats));
146144

@@ -153,9 +151,9 @@ describe('bundle-calculator', () => {
153151
});
154152

155153
it('yields exceeded total scripts budget', () => {
156-
const budgets: Budget[] = [
154+
const budgets: BudgetEntry[] = [
157155
{
158-
type: Type.AllScript,
156+
type: BudgetType.AllScript,
159157
maximumError: '1kb',
160158
},
161159
];
@@ -182,7 +180,7 @@ describe('bundle-calculator', () => {
182180
size: 1.5 * KB,
183181
},
184182
],
185-
} as unknown as StatsCompilation;
183+
};
186184

187185
const failures = Array.from(checkBudgets(budgets, stats));
188186

@@ -195,9 +193,9 @@ describe('bundle-calculator', () => {
195193
});
196194

197195
it('yields exceeded total budget', () => {
198-
const budgets: Budget[] = [
196+
const budgets: BudgetEntry[] = [
199197
{
200-
type: Type.All,
198+
type: BudgetType.All,
201199
maximumError: '1kb',
202200
},
203201
];
@@ -220,7 +218,7 @@ describe('bundle-calculator', () => {
220218
size: 0.75 * KB,
221219
},
222220
],
223-
} as unknown as StatsCompilation;
221+
};
224222

225223
const failures = Array.from(checkBudgets(budgets, stats));
226224

@@ -233,9 +231,9 @@ describe('bundle-calculator', () => {
233231
});
234232

235233
it('skips component style budgets', () => {
236-
const budgets: Budget[] = [
234+
const budgets: BudgetEntry[] = [
237235
{
238-
type: Type.AnyComponentStyle,
236+
type: BudgetType.AnyComponentStyle,
239237
maximumError: '1kb',
240238
},
241239
];
@@ -258,17 +256,17 @@ describe('bundle-calculator', () => {
258256
size: 0.5 * KB,
259257
},
260258
],
261-
} as unknown as StatsCompilation;
259+
};
262260

263261
const failures = Array.from(checkBudgets(budgets, stats));
264262

265263
expect(failures.length).toBe(0);
266264
});
267265

268266
it('yields exceeded individual script budget', () => {
269-
const budgets: Budget[] = [
267+
const budgets: BudgetEntry[] = [
270268
{
271-
type: Type.AnyScript,
269+
type: BudgetType.AnyScript,
272270
maximumError: '1kb',
273271
},
274272
];
@@ -291,7 +289,7 @@ describe('bundle-calculator', () => {
291289
size: 0.5 * KB,
292290
},
293291
],
294-
} as unknown as StatsCompilation;
292+
};
295293

296294
const failures = Array.from(checkBudgets(budgets, stats));
297295

@@ -304,9 +302,9 @@ describe('bundle-calculator', () => {
304302
});
305303

306304
it('yields exceeded individual file budget', () => {
307-
const budgets: Budget[] = [
305+
const budgets: BudgetEntry[] = [
308306
{
309-
type: Type.Any,
307+
type: BudgetType.Any,
310308
maximumError: '1kb',
311309
},
312310
];
@@ -329,7 +327,7 @@ describe('bundle-calculator', () => {
329327
size: 0.5 * KB,
330328
},
331329
],
332-
} as unknown as StatsCompilation;
330+
};
333331

334332
const failures = Array.from(checkBudgets(budgets, stats));
335333

0 commit comments

Comments
 (0)