@@ -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
@@ -353,7 +366,9 @@ export function buildWebpackBrowser(
353
366
filename,
354
367
code,
355
368
map,
356
- name : file . name ,
369
+ // id is always present for non-assets
370
+ // tslint:disable-next-line: no-non-null-assertion
371
+ name : file . id ! ,
357
372
optimizeOnly : true ,
358
373
} ) ;
359
374
@@ -367,7 +382,9 @@ export function buildWebpackBrowser(
367
382
filename,
368
383
code,
369
384
map,
370
- name : file . name ,
385
+ // id is always present for non-assets
386
+ // tslint:disable-next-line: no-non-null-assertion
387
+ name : file . id ! ,
371
388
runtime : file . file . startsWith ( 'runtime' ) ,
372
389
ignoreOriginal : es5Polyfills ,
373
390
} ) ;
@@ -611,6 +628,67 @@ export function buildWebpackBrowser(
611
628
}
612
629
613
630
context . logger . info ( 'ES5 bundle generation complete.' ) ;
631
+
632
+ type ArrayElement < A > = A extends ReadonlyArray < infer T > ? T : never ;
633
+ function generateBundleInfoStats (
634
+ id : string | number ,
635
+ bundle : ProcessBundleFile ,
636
+ chunk : ArrayElement < webpack . Stats . ToJsonOutput [ 'chunks' ] > | undefined ,
637
+ ) : string {
638
+ return generateBundleStats (
639
+ {
640
+ id,
641
+ size : bundle . size ,
642
+ files : bundle . map ? [ bundle . filename , bundle . map . filename ] : [ bundle . filename ] ,
643
+ names : chunk && chunk . names ,
644
+ entry : ! ! chunk && chunk . names . includes ( 'runtime' ) ,
645
+ initial : ! ! chunk && chunk . initial ,
646
+ rendered : true ,
647
+ } ,
648
+ true ,
649
+ ) ;
650
+ }
651
+
652
+ let bundleInfoText = '' ;
653
+ const processedNames = new Set < string > ( ) ;
654
+ for ( const result of processResults ) {
655
+ processedNames . add ( result . name ) ;
656
+
657
+ const chunk =
658
+ webpackStats &&
659
+ webpackStats . chunks &&
660
+ webpackStats . chunks . find ( c => result . name === c . id . toString ( ) ) ;
661
+ if ( result . original ) {
662
+ bundleInfoText +=
663
+ '\n' + generateBundleInfoStats ( result . name , result . original , chunk ) ;
664
+ }
665
+ if ( result . downlevel ) {
666
+ bundleInfoText +=
667
+ '\n' + generateBundleInfoStats ( result . name , result . downlevel , chunk ) ;
668
+ }
669
+ }
670
+
671
+ if ( webpackStats && webpackStats . chunks ) {
672
+ for ( const chunk of webpackStats . chunks ) {
673
+ if ( processedNames . has ( chunk . id . toString ( ) ) ) {
674
+ continue ;
675
+ }
676
+
677
+ const asset =
678
+ webpackStats . assets && webpackStats . assets . find ( a => a . name === chunk . files [ 0 ] ) ;
679
+ bundleInfoText +=
680
+ '\n' + generateBundleStats ( { ...chunk , size : asset && asset . size } , true ) ;
681
+ }
682
+ }
683
+
684
+ bundleInfoText +=
685
+ '\n' +
686
+ generateBuildStats (
687
+ ( webpackStats && webpackStats . hash ) || '<unknown>' ,
688
+ Date . now ( ) - startTime ,
689
+ true ,
690
+ ) ;
691
+ context . logger . info ( bundleInfoText ) ;
614
692
} else {
615
693
const { emittedFiles = [ ] } = firstBuild ;
616
694
files = emittedFiles . filter ( x => x . name !== 'polyfills-es5' ) ;
0 commit comments