@@ -12,6 +12,7 @@ import * as path from 'path';
12
12
import textTable from 'text-table' ;
13
13
import { Configuration , StatsCompilation } from 'webpack' ;
14
14
import { Schema as BrowserBuilderOptions } from '../../builders/browser/schema' ;
15
+ import { BudgetCalculatorResult } from '../../utils/bundle-calculator' ;
15
16
import { colors as ansiColors , removeColor } from '../../utils/color' ;
16
17
import { markAsyncChunksNonInitial } from './async-chunks' ;
17
18
import { getStatsOptions , normalizeExtraEntryPoints } from './helpers' ;
@@ -71,36 +72,67 @@ function generateBuildStatsTable(
71
72
colors : boolean ,
72
73
showTotalSize : boolean ,
73
74
showEstimatedTransferSize : boolean ,
75
+ budgetFailures ?: BudgetCalculatorResult [ ] ,
74
76
) : string {
75
77
const g = ( x : string ) => ( colors ? ansiColors . greenBright ( x ) : x ) ;
76
78
const c = ( x : string ) => ( colors ? ansiColors . cyanBright ( x ) : x ) ;
79
+ const r = ( x : string ) => ( colors ? ansiColors . redBright ( x ) : x ) ;
80
+ const y = ( x : string ) => ( colors ? ansiColors . yellowBright ( x ) : x ) ;
77
81
const bold = ( x : string ) => ( colors ? ansiColors . bold ( x ) : x ) ;
78
82
const dim = ( x : string ) => ( colors ? ansiColors . dim ( x ) : x ) ;
79
83
84
+ const getSizeColor = ( name : string , file ?: string , defaultColor = c ) => {
85
+ const severity = budgets . get ( name ) || ( file && budgets . get ( file ) ) ;
86
+ switch ( severity ) {
87
+ case 'warning' :
88
+ return y ;
89
+ case 'error' :
90
+ return r ;
91
+ default :
92
+ return defaultColor ;
93
+ }
94
+ } ;
95
+
80
96
const changedEntryChunksStats : BundleStatsData [ ] = [ ] ;
81
97
const changedLazyChunksStats : BundleStatsData [ ] = [ ] ;
82
98
83
99
let initialTotalRawSize = 0 ;
84
100
let initialTotalEstimatedTransferSize ;
85
101
102
+ const budgets = new Map < string , string > ( ) ;
103
+ if ( budgetFailures ) {
104
+ for ( const { label, severity } of budgetFailures ) {
105
+ // In some cases a file can have multiple budget failures.
106
+ // Favor error.
107
+ if ( label && ( ! budgets . has ( label ) || budgets . get ( label ) === 'warning' ) ) {
108
+ budgets . set ( label , severity ) ;
109
+ }
110
+ }
111
+ }
112
+
86
113
for ( const { initial, stats } of data ) {
87
114
const [ files , names , rawSize , estimatedTransferSize ] = stats ;
88
-
115
+ const getRawSizeColor = getSizeColor ( names , files ) ;
89
116
let data : BundleStatsData ;
90
117
91
118
if ( showEstimatedTransferSize ) {
92
119
data = [
93
120
g ( files ) ,
94
121
names ,
95
- c ( typeof rawSize === 'number' ? formatSize ( rawSize ) : rawSize ) ,
122
+ getRawSizeColor ( typeof rawSize === 'number' ? formatSize ( rawSize ) : rawSize ) ,
96
123
c (
97
124
typeof estimatedTransferSize === 'number'
98
125
? formatSize ( estimatedTransferSize )
99
126
: estimatedTransferSize ,
100
127
) ,
101
128
] ;
102
129
} else {
103
- data = [ g ( files ) , names , c ( typeof rawSize === 'number' ? formatSize ( rawSize ) : rawSize ) , '' ] ;
130
+ data = [
131
+ g ( files ) ,
132
+ names ,
133
+ getRawSizeColor ( typeof rawSize === 'number' ? formatSize ( rawSize ) : rawSize ) ,
134
+ '' ,
135
+ ] ;
104
136
}
105
137
106
138
if ( initial ) {
@@ -135,7 +167,12 @@ function generateBuildStatsTable(
135
167
if ( showTotalSize ) {
136
168
bundleInfo . push ( [ ] ) ;
137
169
138
- const totalSizeElements = [ ' ' , 'Initial Total' , formatSize ( initialTotalRawSize ) ] ;
170
+ const initialSizeTotalColor = getSizeColor ( 'bundle initial' , undefined , ( x ) => x ) ;
171
+ const totalSizeElements = [
172
+ ' ' ,
173
+ 'Initial Total' ,
174
+ initialSizeTotalColor ( formatSize ( initialTotalRawSize ) ) ,
175
+ ] ;
139
176
if ( showEstimatedTransferSize ) {
140
177
totalSizeElements . push (
141
178
typeof initialTotalEstimatedTransferSize === 'number'
@@ -180,7 +217,7 @@ function statsToString(
180
217
json : StatsCompilation ,
181
218
// eslint-disable-next-line @typescript-eslint/no-explicit-any
182
219
statsConfig : any ,
183
- bundleState ?: BundleStats [ ] ,
220
+ budgetFailures ?: BudgetCalculatorResult [ ] ,
184
221
) : string {
185
222
if ( ! json . chunks ?. length ) {
186
223
return '' ;
@@ -189,45 +226,44 @@ function statsToString(
189
226
const colors = statsConfig . colors ;
190
227
const rs = ( x : string ) => ( colors ? ansiColors . reset ( x ) : x ) ;
191
228
192
- const changedChunksStats : BundleStats [ ] = bundleState ?? [ ] ;
229
+ const changedChunksStats : BundleStats [ ] = [ ] ;
193
230
let unchangedChunkNumber = 0 ;
194
231
let hasEstimatedTransferSizes = false ;
195
- if ( ! bundleState ?. length ) {
196
- const isFirstRun = ! runsCache . has ( json . outputPath || '' ) ;
197
-
198
- for ( const chunk of json . chunks ) {
199
- // During first build we want to display unchanged chunks
200
- // but unchanged cached chunks are always marked as not rendered.
201
- if ( ! isFirstRun && ! chunk . rendered ) {
202
- continue ;
203
- }
204
232
205
- const assets = json . assets ?. filter ( ( asset ) => chunk . files ?. includes ( asset . name ) ) ;
206
- let rawSize = 0 ;
207
- let estimatedTransferSize ;
208
- if ( assets ) {
209
- for ( const asset of assets ) {
210
- if ( asset . name . endsWith ( '.map' ) ) {
211
- continue ;
212
- }
233
+ const isFirstRun = ! runsCache . has ( json . outputPath || '' ) ;
234
+
235
+ for ( const chunk of json . chunks ) {
236
+ // During first build we want to display unchanged chunks
237
+ // but unchanged cached chunks are always marked as not rendered.
238
+ if ( ! isFirstRun && ! chunk . rendered ) {
239
+ continue ;
240
+ }
241
+
242
+ const assets = json . assets ?. filter ( ( asset ) => chunk . files ?. includes ( asset . name ) ) ;
243
+ let rawSize = 0 ;
244
+ let estimatedTransferSize ;
245
+ if ( assets ) {
246
+ for ( const asset of assets ) {
247
+ if ( asset . name . endsWith ( '.map' ) ) {
248
+ continue ;
249
+ }
213
250
214
- rawSize += asset . size ;
251
+ rawSize += asset . size ;
215
252
216
- if ( typeof asset . info . estimatedTransferSize === 'number' ) {
217
- if ( estimatedTransferSize === undefined ) {
218
- estimatedTransferSize = 0 ;
219
- hasEstimatedTransferSizes = true ;
220
- }
221
- estimatedTransferSize += asset . info . estimatedTransferSize ;
253
+ if ( typeof asset . info . estimatedTransferSize === 'number' ) {
254
+ if ( estimatedTransferSize === undefined ) {
255
+ estimatedTransferSize = 0 ;
256
+ hasEstimatedTransferSizes = true ;
222
257
}
258
+ estimatedTransferSize += asset . info . estimatedTransferSize ;
223
259
}
224
260
}
225
- changedChunksStats . push ( generateBundleStats ( { ...chunk , rawSize, estimatedTransferSize } ) ) ;
226
261
}
227
- unchangedChunkNumber = json . chunks . length - changedChunksStats . length ;
228
-
229
- runsCache . add ( json . outputPath || '' ) ;
262
+ changedChunksStats . push ( generateBundleStats ( { ...chunk , rawSize, estimatedTransferSize } ) ) ;
230
263
}
264
+ unchangedChunkNumber = json . chunks . length - changedChunksStats . length ;
265
+
266
+ runsCache . add ( json . outputPath || '' ) ;
231
267
232
268
// Sort chunks by size in descending order
233
269
changedChunksStats . sort ( ( a , b ) => {
@@ -247,6 +283,7 @@ function statsToString(
247
283
colors ,
248
284
unchangedChunkNumber === 0 ,
249
285
hasEstimatedTransferSizes ,
286
+ budgetFailures ,
250
287
) ;
251
288
252
289
// In some cases we do things outside of webpack context
@@ -387,9 +424,9 @@ export function webpackStatsLogger(
387
424
logger : logging . LoggerApi ,
388
425
json : StatsCompilation ,
389
426
config : Configuration ,
390
- bundleStats ?: BundleStats [ ] ,
427
+ budgetFailures ?: BudgetCalculatorResult [ ] ,
391
428
) : void {
392
- logger . info ( statsToString ( json , config . stats , bundleStats ) ) ;
429
+ logger . info ( statsToString ( json , config . stats , budgetFailures ) ) ;
393
430
394
431
if ( statsHasWarnings ( json ) ) {
395
432
logger . warn ( statsWarningsToString ( json , config . stats ) ) ;
0 commit comments