@@ -27,7 +27,6 @@ import { NodeJsSyncHost } from '@angular-devkit/core/node';
27
27
import { createHash } from 'crypto' ;
28
28
import * as findCacheDirectory from 'find-cache-dir' ;
29
29
import * as fs from 'fs' ;
30
- import * as os from 'os' ;
31
30
import * as path from 'path' ;
32
31
import { from , of } from 'rxjs' ;
33
32
import { bufferCount , catchError , concatMap , map , mergeScan , switchMap } from 'rxjs/operators' ;
@@ -53,6 +52,8 @@ import {
53
52
import { readTsconfig } from '../angular-cli-files/utilities/read-tsconfig' ;
54
53
import { augmentAppWithServiceWorker } from '../angular-cli-files/utilities/service-worker' ;
55
54
import {
55
+ generateBuildStats ,
56
+ generateBundleStats ,
56
57
statsErrorsToString ,
57
58
statsToString ,
58
59
statsWarningsToString ,
@@ -66,7 +67,12 @@ import {
66
67
normalizeSourceMaps ,
67
68
} from '../utils' ;
68
69
import { manglingDisabled } from '../utils/mangle-options' ;
69
- import { CacheKey , ProcessBundleOptions , ProcessBundleResult } from '../utils/process-bundle' ;
70
+ import {
71
+ CacheKey ,
72
+ ProcessBundleFile ,
73
+ ProcessBundleOptions ,
74
+ ProcessBundleResult ,
75
+ } from '../utils/process-bundle' ;
70
76
import { assertCompatibleAngularVersion } from '../utils/version' ;
71
77
import {
72
78
generateBrowserWebpackConfigFromContext ,
@@ -200,9 +206,6 @@ export function buildWebpackBrowser(
200
206
// Check Angular version.
201
207
assertCompatibleAngularVersion ( context . workspaceRoot , context . logger ) ;
202
208
203
- const loggingFn =
204
- transforms . logging || createBrowserLoggingCallback ( ! ! options . verbose , context . logger ) ;
205
-
206
209
return from ( initialize ( options , context , host , transforms . webpackConfiguration ) ) . pipe (
207
210
// tslint:disable-next-line: no-big-function
208
211
switchMap ( ( { workspace, config : configs } ) => {
@@ -233,14 +236,24 @@ export function buildWebpackBrowser(
233
236
` ) ;
234
237
}
235
238
239
+ const useBundleDownleveling =
240
+ isDifferentialLoadingNeeded && ! ( fullDifferential || options . watch ) ;
241
+ const startTime = Date . now ( ) ;
242
+
236
243
return from ( configs ) . pipe (
237
244
// the concurrency parameter (3rd parameter of mergeScan) is deliberately
238
245
// set to 1 to make sure the build steps are executed in sequence.
239
246
mergeScan (
240
247
( lastResult , config ) => {
241
248
// Make sure to only run the 2nd build step, if 1st one succeeded
242
249
if ( lastResult . success ) {
243
- return runWebpack ( config , context , { logging : loggingFn } ) ;
250
+ return runWebpack ( config , context , {
251
+ logging :
252
+ transforms . logging ||
253
+ ( useBundleDownleveling
254
+ ? ( ) => { }
255
+ : createBrowserLoggingCallback ( ! ! options . verbose , context . logger ) ) ,
256
+ } ) ;
244
257
} else {
245
258
return of ( ) ;
246
259
}
@@ -274,7 +287,7 @@ export function buildWebpackBrowser(
274
287
noModuleFiles = secondBuild . emittedFiles ;
275
288
}
276
289
} else if ( isDifferentialLoadingNeeded && ! fullDifferential ) {
277
- const { emittedFiles = [ ] } = firstBuild ;
290
+ const { emittedFiles = [ ] , webpackStats } = firstBuild ;
278
291
moduleFiles = [ ] ;
279
292
noModuleFiles = [ ] ;
280
293
@@ -611,6 +624,68 @@ export function buildWebpackBrowser(
611
624
}
612
625
613
626
context . logger . info ( 'ES5 bundle generation complete.' ) ;
627
+
628
+ type ArrayElement < A > = A extends ReadonlyArray < infer T > ? T : never ;
629
+ function generateBundleInfoStats (
630
+ name : string | undefined ,
631
+ bundle : ProcessBundleFile ,
632
+ chunk : ArrayElement < webpack . Stats . ToJsonOutput [ 'chunks' ] > | undefined ,
633
+ ) : string {
634
+ return generateBundleStats (
635
+ {
636
+ id : chunk ? chunk . id . toString ( ) : '' ,
637
+ size : bundle . size ,
638
+ files : bundle . map ? [ bundle . filename , bundle . map . filename ] : [ bundle . filename ] ,
639
+ names : name ? [ name ] : [ ] ,
640
+ entry : name === 'runtime' ,
641
+ initial : ! ! chunk && chunk . initial ,
642
+ rendered : true ,
643
+ } ,
644
+ true ,
645
+ ) ;
646
+ }
647
+
648
+ let bundleInfoText = '' ;
649
+ const processedNames = new Set < string > ( ) ;
650
+ for ( const result of processResults ) {
651
+ if ( result . name ) {
652
+ processedNames . add ( result . name ) ;
653
+ }
654
+ const chunk =
655
+ webpackStats &&
656
+ webpackStats . chunks &&
657
+ webpackStats . chunks . find ( c => result . name && c . names . includes ( result . name ) ) ;
658
+ if ( result . original ) {
659
+ bundleInfoText +=
660
+ '\n' + generateBundleInfoStats ( result . name , result . original , chunk ) ;
661
+ }
662
+ if ( result . downlevel ) {
663
+ bundleInfoText +=
664
+ '\n' + generateBundleInfoStats ( result . name , result . downlevel , chunk ) ;
665
+ }
666
+ }
667
+
668
+ if ( webpackStats && webpackStats . chunks ) {
669
+ for ( const chunk of webpackStats . chunks ) {
670
+ if ( chunk . names . some ( n => processedNames . has ( n ) ) ) {
671
+ continue ;
672
+ }
673
+
674
+ const asset =
675
+ webpackStats . assets && webpackStats . assets . find ( a => a . name === chunk . files [ 0 ] ) ;
676
+ bundleInfoText +=
677
+ '\n' + generateBundleStats ( { ...chunk , size : asset && asset . size } , true ) ;
678
+ }
679
+ }
680
+
681
+ bundleInfoText +=
682
+ '\n' +
683
+ generateBuildStats (
684
+ ( webpackStats && webpackStats . hash ) || '<unknown>' ,
685
+ Date . now ( ) - startTime ,
686
+ true ,
687
+ ) ;
688
+ context . logger . info ( bundleInfoText ) ;
614
689
} else {
615
690
const { emittedFiles = [ ] } = firstBuild ;
616
691
files = emittedFiles . filter ( x => x . name !== 'polyfills-es5' ) ;
0 commit comments