-
Notifications
You must be signed in to change notification settings - Fork 12k
/
Copy pathbundle-budget.ts
119 lines (101 loc) · 3.92 KB
/
bundle-budget.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import { Compiler, compilation } from 'webpack';
import { Budget } from '../../browser/schema';
import { Size, calculateBytes, calculateSizes } from '../utilities/bundle-calculator';
import { formatSize } from '../utilities/stats';
interface Thresholds {
maximumWarning?: number;
maximumError?: number;
minimumWarning?: number;
minimumError?: number;
warningLow?: number;
warningHigh?: number;
errorLow?: number;
errorHigh?: number;
}
export interface BundleBudgetPluginOptions {
budgets: Budget[];
}
export class BundleBudgetPlugin {
constructor(private options: BundleBudgetPluginOptions) { }
apply(compiler: Compiler): void {
const { budgets } = this.options;
compiler.hooks.afterEmit.tap('BundleBudgetPlugin', (compilation: compilation.Compilation) => {
if (!budgets || budgets.length === 0) {
return;
}
budgets.map(budget => {
const thresholds = this.calculate(budget);
return {
budget,
thresholds,
sizes: calculateSizes(budget, compilation),
};
})
.forEach(budgetCheck => {
budgetCheck.sizes.forEach(size => {
this.checkMaximum(budgetCheck.thresholds.maximumWarning, size, compilation.warnings);
this.checkMaximum(budgetCheck.thresholds.maximumError, size, compilation.errors);
this.checkMinimum(budgetCheck.thresholds.minimumWarning, size, compilation.warnings);
this.checkMinimum(budgetCheck.thresholds.minimumError, size, compilation.errors);
this.checkMinimum(budgetCheck.thresholds.warningLow, size, compilation.warnings);
this.checkMaximum(budgetCheck.thresholds.warningHigh, size, compilation.warnings);
this.checkMinimum(budgetCheck.thresholds.errorLow, size, compilation.errors);
this.checkMaximum(budgetCheck.thresholds.errorHigh, size, compilation.errors);
});
});
});
}
private checkMinimum(threshold: number | undefined, size: Size, messages: string[]) {
if (threshold) {
if (threshold > size.size) {
const sizeDifference = formatSize(threshold - size.size);
messages.push(`budgets, minimum exceeded for ${size.label}. `
+ `Budget ${formatSize(threshold)} was not reached by ${sizeDifference}.`);
}
}
}
private checkMaximum(threshold: number | undefined, size: Size, messages: string[]) {
if (threshold) {
if (threshold < size.size) {
const sizeDifference = formatSize(size.size - threshold);
messages.push(`budgets, maximum exceeded for ${size.label}. `
+ `Budget ${formatSize(threshold)} was exceeded by ${sizeDifference}.`);
}
}
}
private calculate(budget: Budget): Thresholds {
const thresholds: Thresholds = {};
if (budget.maximumWarning) {
thresholds.maximumWarning = calculateBytes(budget.maximumWarning, budget.baseline, 1);
}
if (budget.maximumError) {
thresholds.maximumError = calculateBytes(budget.maximumError, budget.baseline, 1);
}
if (budget.minimumWarning) {
thresholds.minimumWarning = calculateBytes(budget.minimumWarning, budget.baseline, -1);
}
if (budget.minimumError) {
thresholds.minimumError = calculateBytes(budget.minimumError, budget.baseline, -1);
}
if (budget.warning) {
thresholds.warningLow = calculateBytes(budget.warning, budget.baseline, -1);
}
if (budget.warning) {
thresholds.warningHigh = calculateBytes(budget.warning, budget.baseline, 1);
}
if (budget.error) {
thresholds.errorLow = calculateBytes(budget.error, budget.baseline, -1);
}
if (budget.error) {
thresholds.errorHigh = calculateBytes(budget.error, budget.baseline, 1);
}
return thresholds;
}
}