1- import * as fs from 'fs' ;
21import * as path from 'path' ;
32import * as logUpdate from 'log-update' ;
43import * as logSymbols from 'log-symbols' ;
5- import * as gzipSize from 'gzip-size' ;
64import * as typescript from 'typescript' ;
75import * as jsonFile from 'jsonfile' ;
6+ import BundleAnalyzer from './webpack-bundle-analyzer/BundleAnalyzer' ;
87import chalk from 'chalk' ;
8+ import { findLargestGroup } from './webpack-bundle-analyzer/parseUtils' ;
99
1010const pkgDir = require ( 'pkg-dir' ) ;
1111const columns = require ( 'cli-columns' ) ;
@@ -15,54 +15,64 @@ const version = jsonFile.readFileSync(path.join(pkgDir.sync(__dirname), 'package
1515export default function logger ( stats : any , config : any , runningMessage : string = '' , args : any = { } ) : boolean {
1616 const singleConfig = Array . isArray ( config ) ? config [ 0 ] : config ;
1717 const outputPath = singleConfig . output . path ;
18- const manifestPath = path . join ( outputPath , 'manifest.json' ) ;
19- let assets : undefined | string [ ] ;
18+ const loggerStats = stats . toJson ( { warningsFilter } ) ;
2019 let chunks : undefined | string [ ] ;
21- if ( fs . existsSync ( manifestPath ) ) {
22- const manifestContent = JSON . parse ( fs . readFileSync ( path . join ( outputPath , 'manifest.json' ) , 'utf8' ) ) ;
23- assets = Object . keys ( manifestContent ) . map ( ( item ) => {
24- const assetName = manifestContent [ item ] ;
25- const filePath = path . join ( outputPath , assetName ) ;
26- if ( fs . existsSync ( filePath ) ) {
27- if ( args . mode === 'dev' || args . mode === 'test' ) {
28- return `${ assetName } ` ;
29- } else {
30- const fileStats = fs . statSync ( filePath ) ;
31- const size = ( fileStats . size / 1000 ) . toFixed ( 2 ) ;
32- const assetInfo = `${ assetName } ${ chalk . yellow ( `(${ size } kb)` ) } ` ;
33- const content = fs . readFileSync ( filePath , 'utf8' ) ;
34- const compressedSize = ( gzipSize . sync ( content ) / 1000 ) . toFixed ( 2 ) ;
35- return `${ assetInfo } / ${ chalk . blue ( `(${ compressedSize } kb gz)` ) } ` ;
36- }
37- }
38- return '' ;
39- } ) ;
4020
41- chunks = ( Array . isArray ( config )
42- ? stats . children . reduce ( ( chunks : any [ ] , current : any ) => [ ...chunks , ...current . chunks ] , [ ] )
43- : stats . chunks
44- ) . map ( ( chunk : any ) => `${ chunk . names [ 0 ] } ` ) ;
21+ let chunkMap : { [ chunk : string ] : any } ;
22+ if ( args . mode === 'dist' ) {
23+ chunkMap = new BundleAnalyzer ( {
24+ analyzerMode : 'static' ,
25+ openAnalyzer : false ,
26+ generateStatsFile : true ,
27+ reportFilename : '../info/report.html' ,
28+ statsFilename : '../info/stats.json'
29+ } ) . analyze ( stats , config ) ;
4530 }
31+ chunks = ( Array . isArray ( config )
32+ ? loggerStats . children . reduce ( ( chunks : any [ ] , current : any ) => [ ...chunks , ...current . chunks ] , [ ] )
33+ : loggerStats . chunks
34+ ) . map ( ( chunk : any ) => {
35+ const chunkName : string = chunk . names [ 0 ] ;
36+ if ( ! chunkMap ) {
37+ return chunkName ;
38+ } else {
39+ const chunkStats = chunkMap [ chunkName ] ;
40+ const size = chunkStats && ( chunkStats . parsedSize || chunkStats . statSize ) ;
41+ const gzipSize = chunkStats && chunkStats . gzipSize ;
42+
43+ const chunkInfo = `${ chunkName } ${ chalk . yellow ( `(${ size } kb)` ) } ${
44+ gzipSize ? `/ ${ chalk . blue ( `(${ gzipSize } kb gz)` ) } ` : ''
45+ } `;
46+
47+ if ( size > 1000 ) {
48+ const largestGroup = findLargestGroup ( chunkStats , 'node_modules' ) ;
49+ if ( largestGroup ) {
50+ return `${ chunkInfo } \nDependency: ${ largestGroup . label } is ${ largestGroup . statSize } kb` ;
51+ }
52+ }
53+ return chunkInfo ;
54+ }
55+ } ) ;
4656
4757 let errors = '' ;
4858 let warnings = '' ;
4959 let chunkAndAssetLog = '' ;
5060 let signOff = chalk . green ( 'The build completed successfully.' ) ;
5161
52- if ( stats . warnings . length ) {
62+ if ( loggerStats . warnings . length ) {
5363 signOff = chalk . yellow ( 'The build completed with warnings.' ) ;
5464 warnings = `
5565${ chalk . yellow ( 'warnings:' ) } ${ chalk . gray (
56- stats . warnings . reduce ( ( warnings : string , warning : string ) => `${ warnings } \n${ stripAnsi ( warning ) } ` , '' )
66+ loggerStats . warnings . reduce ( ( warnings : string , warning : string ) => `${ warnings } \n${ stripAnsi ( warning ) } ` , '' )
5767 ) }
5868` ;
5969 }
6070
61- if ( stats . errors . length ) {
71+ if ( loggerStats . errors . length ) {
6272 signOff = chalk . red ( 'The build completed with errors.' ) ;
6373 errors = `
6474${ chalk . yellow ( 'errors:' ) } ${ chalk . red (
65- stats . errors . reduce ( ( errors : string , error : string ) => `${ errors } \n${ stripAnsi ( error ) } ` , '' )
75+ loggerStats . errors . reduce ( ( errors : string , error : string ) => `${ errors } \n${ stripAnsi ( error ) } ` , '' )
6676 ) }
6777` ;
6878 }
@@ -76,18 +86,12 @@ ${chalk.yellow('errors:')}${chalk.red(
7686${ columns ( chunks ) } `;
7787 }
7888
79- if ( assets ) {
80- chunkAndAssetLog = `${ chunkAndAssetLog }
81- ${ chalk . yellow ( 'assets:' ) }
82- ${ columns ( assets ) } `;
83- }
84-
8589 logUpdate ( `
8690${ logSymbols . info } cli-build-app: ${ version }
8791${ logSymbols . info } typescript: ${ typescript . version }
88- ${ logSymbols . success } hash: ${ stats . hash }
89- ${ logSymbols . error } errors: ${ stats . errors . length }
90- ${ logSymbols . warning } warnings: ${ stats . warnings . length }
92+ ${ logSymbols . success } hash: ${ loggerStats . hash }
93+ ${ logSymbols . error } errors: ${ loggerStats . errors . length }
94+ ${ logSymbols . warning } warnings: ${ loggerStats . warnings . length }
9195${ errors } ${ warnings }
9296${ chunkAndAssetLog }
9397${ chalk . yellow ( `output at: ${ chalk . cyan ( chalk . underline ( `file:///${ outputPath } ` ) ) } ` ) }
@@ -96,3 +100,7 @@ ${signOff}
96100 ` ) ;
97101 return ! ! errors ;
98102}
103+
104+ function warningsFilter ( warning : string ) {
105+ return warning . includes ( '[mini-css-extract-plugin]\nConflicting order between' ) ;
106+ }
0 commit comments