@@ -51,6 +51,8 @@ import {
51
51
import { readTsconfig } from '../angular-cli-files/utilities/read-tsconfig' ;
52
52
import { augmentAppWithServiceWorker } from '../angular-cli-files/utilities/service-worker' ;
53
53
import {
54
+ generateBuildStats ,
55
+ generateBundleStats ,
54
56
statsErrorsToString ,
55
57
statsToString ,
56
58
statsWarningsToString ,
@@ -64,7 +66,12 @@ import {
64
66
normalizeSourceMaps ,
65
67
} from '../utils' ;
66
68
import { manglingDisabled } from '../utils/mangle-options' ;
67
- import { CacheKey , ProcessBundleOptions , ProcessBundleResult } from '../utils/process-bundle' ;
69
+ import {
70
+ CacheKey ,
71
+ ProcessBundleFile ,
72
+ ProcessBundleOptions ,
73
+ ProcessBundleResult ,
74
+ } from '../utils/process-bundle' ;
68
75
import { assertCompatibleAngularVersion } from '../utils/version' ;
69
76
import {
70
77
generateBrowserWebpackConfigFromContext ,
@@ -202,9 +209,6 @@ export function buildWebpackBrowser(
202
209
// Check Angular version.
203
210
assertCompatibleAngularVersion ( context . workspaceRoot , context . logger ) ;
204
211
205
- const loggingFn =
206
- transforms . logging || createBrowserLoggingCallback ( ! ! options . verbose , context . logger ) ;
207
-
208
212
return from ( initialize ( options , context , host , transforms . webpackConfiguration ) ) . pipe (
209
213
// tslint:disable-next-line: no-big-function
210
214
switchMap ( ( { config : configs , projectRoot } ) => {
@@ -222,14 +226,24 @@ export function buildWebpackBrowser(
222
226
` ) ;
223
227
}
224
228
229
+ const useBundleDownleveling =
230
+ isDifferentialLoadingNeeded && ! ( fullDifferential || options . watch ) ;
231
+ const startTime = Date . now ( ) ;
232
+
225
233
return from ( configs ) . pipe (
226
234
// the concurrency parameter (3rd parameter of mergeScan) is deliberately
227
235
// set to 1 to make sure the build steps are executed in sequence.
228
236
mergeScan (
229
237
( lastResult , config ) => {
230
238
// Make sure to only run the 2nd build step, if 1st one succeeded
231
239
if ( lastResult . success ) {
232
- return runWebpack ( config , context , { logging : loggingFn } ) ;
240
+ return runWebpack ( config , context , {
241
+ logging :
242
+ transforms . logging ||
243
+ ( useBundleDownleveling
244
+ ? ( ) => { }
245
+ : createBrowserLoggingCallback ( ! ! options . verbose , context . logger ) ) ,
246
+ } ) ;
233
247
} else {
234
248
return of ( ) ;
235
249
}
@@ -263,7 +277,7 @@ export function buildWebpackBrowser(
263
277
noModuleFiles = secondBuild . emittedFiles ;
264
278
}
265
279
} else if ( isDifferentialLoadingNeeded && ! fullDifferential ) {
266
- const { emittedFiles = [ ] } = firstBuild ;
280
+ const { emittedFiles = [ ] , webpackStats } = firstBuild ;
267
281
moduleFiles = [ ] ;
268
282
noModuleFiles = [ ] ;
269
283
@@ -342,7 +356,9 @@ export function buildWebpackBrowser(
342
356
filename,
343
357
code,
344
358
map,
345
- name : file . name ,
359
+ // id is always present for non-assets
360
+ // tslint:disable-next-line: no-non-null-assertion
361
+ name : file . id ! ,
346
362
optimizeOnly : true ,
347
363
} ) ;
348
364
@@ -356,7 +372,9 @@ export function buildWebpackBrowser(
356
372
filename,
357
373
code,
358
374
map,
359
- name : file . name ,
375
+ // id is always present for non-assets
376
+ // tslint:disable-next-line: no-non-null-assertion
377
+ name : file . id ! ,
360
378
runtime : file . file . startsWith ( 'runtime' ) ,
361
379
ignoreOriginal : es5Polyfills ,
362
380
} ) ;
@@ -600,6 +618,67 @@ export function buildWebpackBrowser(
600
618
}
601
619
602
620
context . logger . info ( 'ES5 bundle generation complete.' ) ;
621
+
622
+ type ArrayElement < A > = A extends ReadonlyArray < infer T > ? T : never ;
623
+ function generateBundleInfoStats (
624
+ id : string | number ,
625
+ bundle : ProcessBundleFile ,
626
+ chunk : ArrayElement < webpack . Stats . ToJsonOutput [ 'chunks' ] > | undefined ,
627
+ ) : string {
628
+ return generateBundleStats (
629
+ {
630
+ id,
631
+ size : bundle . size ,
632
+ files : bundle . map ? [ bundle . filename , bundle . map . filename ] : [ bundle . filename ] ,
633
+ names : chunk && chunk . names ,
634
+ entry : ! ! chunk && chunk . names . includes ( 'runtime' ) ,
635
+ initial : ! ! chunk && chunk . initial ,
636
+ rendered : true ,
637
+ } ,
638
+ true ,
639
+ ) ;
640
+ }
641
+
642
+ let bundleInfoText = '' ;
643
+ const processedNames = new Set < string > ( ) ;
644
+ for ( const result of processResults ) {
645
+ processedNames . add ( result . name ) ;
646
+
647
+ const chunk =
648
+ webpackStats &&
649
+ webpackStats . chunks &&
650
+ webpackStats . chunks . find ( c => result . name === c . id . toString ( ) ) ;
651
+ if ( result . original ) {
652
+ bundleInfoText +=
653
+ '\n' + generateBundleInfoStats ( result . name , result . original , chunk ) ;
654
+ }
655
+ if ( result . downlevel ) {
656
+ bundleInfoText +=
657
+ '\n' + generateBundleInfoStats ( result . name , result . downlevel , chunk ) ;
658
+ }
659
+ }
660
+
661
+ if ( webpackStats && webpackStats . chunks ) {
662
+ for ( const chunk of webpackStats . chunks ) {
663
+ if ( processedNames . has ( chunk . id . toString ( ) ) ) {
664
+ continue ;
665
+ }
666
+
667
+ const asset =
668
+ webpackStats . assets && webpackStats . assets . find ( a => a . name === chunk . files [ 0 ] ) ;
669
+ bundleInfoText +=
670
+ '\n' + generateBundleStats ( { ...chunk , size : asset && asset . size } , true ) ;
671
+ }
672
+ }
673
+
674
+ bundleInfoText +=
675
+ '\n' +
676
+ generateBuildStats (
677
+ ( webpackStats && webpackStats . hash ) || '<unknown>' ,
678
+ Date . now ( ) - startTime ,
679
+ true ,
680
+ ) ;
681
+ context . logger . info ( bundleInfoText ) ;
603
682
} else {
604
683
const { emittedFiles = [ ] } = firstBuild ;
605
684
files = emittedFiles . filter ( x => x . name !== 'polyfills-es5' ) ;
0 commit comments