@@ -18,79 +18,115 @@ var rimrafSync = require('rimraf').sync;
18
18
var webpack = require ( 'webpack' ) ;
19
19
var config = require ( '../config/webpack.config.prod' ) ;
20
20
var paths = require ( '../config/paths' ) ;
21
+ var recursive = require ( 'recursive-readdir' ) ;
21
22
22
- // Remove all content but keep the directory so that
23
- // if you're in it, you don't end up in Trash
24
- rimrafSync ( paths . appBuild + '/*' ) ;
23
+ function removeFileNameHash ( fileName ) {
24
+ return fileName . replace ( paths . appBuild , '' )
25
+ . replace ( / \/ ? ( .* ) ( \. \w + ) ( \. j s | \. c s s ) / , function ( match , p1 , p2 , p3 ) {
26
+ return p1 + p3 ;
27
+ } ) ;
28
+ }
25
29
26
- console . log ( 'Creating an optimized production build...' ) ;
27
- webpack ( config ) . run ( function ( err , stats ) {
28
- if ( err ) {
29
- console . error ( 'Failed to create a production build. Reason:' ) ;
30
- console . error ( err . message || err ) ;
31
- process . exit ( 1 ) ;
30
+ function sizeDifference ( currentSize , previousSize ) {
31
+ if ( previousSize === undefined ) { return '' ; }
32
+ var difference = currentSize - previousSize ;
33
+ var fileSize = filesize ( difference ) ;
34
+ if ( difference > 0 ) {
35
+ return chalk . red ( '+' + fileSize ) ;
36
+ } else if ( difference <= 0 ) {
37
+ return chalk . green ( ( difference === 0 ? '+' : '' ) + fileSize ) ;
32
38
}
39
+ }
33
40
34
- console . log ( chalk . green ( 'Compiled successfully.' ) ) ;
35
- console . log ( ) ;
41
+ recursive ( paths . appBuild , function ( err , fileNames ) {
42
+ fileNames = fileNames || [ ] ;
43
+ var previousSizeMap = fileNames . filter ( fileName => / \. ( j s | c s s ) $ / . test ( fileName ) )
44
+ . reduce ( ( memo , fileName ) => {
45
+ var contents = fs . readFileSync ( fileName ) ;
46
+ var key = removeFileNameHash ( fileName ) ;
47
+ memo [ key ] = gzipSize ( contents ) ;
48
+ return memo ;
49
+ } , { } ) ;
36
50
37
- console . log ( 'File sizes after gzip:' ) ;
38
- console . log ( ) ;
39
- var assets = stats . toJson ( ) . assets
40
- . filter ( asset => / \. ( j s | c s s ) $ / . test ( asset . name ) )
41
- . map ( asset => {
42
- var fileContents = fs . readFileSync ( paths . appBuild + '/' + asset . name ) ;
43
- var size = gzipSize ( fileContents ) ;
44
- return {
45
- folder : path . join ( 'build' , path . dirname ( asset . name ) ) ,
46
- name : path . basename ( asset . name ) ,
47
- size : size ,
48
- sizeLabel : filesize ( size )
49
- } ;
50
- } ) ;
51
- assets . sort ( ( a , b ) => b . size - a . size ) ;
51
+ // Remove all content but keep the directory so that
52
+ // if you're in it, you don't end up in Trash
53
+ rimrafSync ( paths . appBuild + '/*' ) ;
54
+
55
+ build ( previousSizeMap ) ;
56
+ } ) ;
52
57
53
- var longestSizeLabelLength = Math . max . apply ( null ,
54
- assets . map ( a => a . sizeLabel . length )
55
- ) ;
56
- assets . forEach ( asset => {
57
- var sizeLabel = asset . sizeLabel ;
58
- if ( sizeLabel . length < longestSizeLabelLength ) {
59
- var rightPadding = ' ' . repeat ( longestSizeLabelLength - sizeLabel . length ) ;
60
- sizeLabel += rightPadding ;
58
+ function build ( previousSizeMap ) {
59
+ console . log ( 'Creating an optimized production build...' ) ;
60
+ webpack ( config ) . run ( function ( err , stats ) {
61
+ if ( err ) {
62
+ console . error ( 'Failed to create a production build. Reason:' ) ;
63
+ console . error ( err . message || err ) ;
64
+ process . exit ( 1 ) ;
61
65
}
62
- console . log (
63
- ' ' + chalk . green ( sizeLabel ) +
64
- ' ' + chalk . dim ( asset . folder + path . sep ) + chalk . cyan ( asset . name )
65
- ) ;
66
- } ) ;
67
- console . log ( ) ;
68
66
69
- var openCommand = process . platform === 'win32' ? 'start' : 'open' ;
70
- var homepagePath = require ( paths . appPackageJson ) . homepage ;
71
- if ( homepagePath ) {
72
- console . log ( 'You can now publish them at ' + homepagePath + '.' ) ;
73
- console . log ( 'For example, if you use GitHub Pages:' ) ;
67
+ console . log ( chalk . green ( 'Compiled successfully.' ) ) ;
74
68
console . log ( ) ;
75
- console . log ( ' git commit -am "Save local changes"' ) ;
76
- console . log ( ' git checkout -B gh-pages' ) ;
77
- console . log ( ' git add -f build' ) ;
78
- console . log ( ' git commit -am "Rebuild website"' ) ;
79
- console . log ( ' git filter-branch -f --prune-empty --subdirectory-filter build' ) ;
80
- console . log ( ' git push -f origin gh-pages' ) ;
81
- console . log ( ' git checkout -' ) ;
69
+
70
+ console . log ( 'File sizes after gzip:' ) ;
82
71
console . log ( ) ;
83
- } else {
84
- console . log ( 'You can now serve them with any static server.' ) ;
85
- console . log ( 'For example:' ) ;
72
+ var assets = stats . toJson ( ) . assets
73
+ . filter ( asset => / \. ( j s | c s s ) $ / . test ( asset . name ) )
74
+ . map ( asset => {
75
+ var fileContents = fs . readFileSync ( paths . appBuild + '/' + asset . name ) ;
76
+ var size = gzipSize ( fileContents ) ;
77
+ var previousSize = previousSizeMap [ removeFileNameHash ( asset . name ) ] ;
78
+ var difference = sizeDifference ( size , previousSize ) ;
79
+ return {
80
+ folder : path . join ( 'build' , path . dirname ( asset . name ) ) ,
81
+ name : path . basename ( asset . name ) ,
82
+ size : size ,
83
+ sizeLabel : filesize ( size ) + ( difference ? ' (' + difference + ')' : '' )
84
+ } ;
85
+ } ) ;
86
+ assets . sort ( ( a , b ) => b . size - a . size ) ;
87
+
88
+ var longestSizeLabelLength = Math . max . apply ( null ,
89
+ assets . map ( a => a . sizeLabel . length )
90
+ ) ;
91
+ assets . forEach ( asset => {
92
+ var sizeLabel = asset . sizeLabel ;
93
+ if ( sizeLabel . length < longestSizeLabelLength ) {
94
+ var rightPadding = ' ' . repeat ( longestSizeLabelLength - sizeLabel . length ) ;
95
+ sizeLabel += rightPadding ;
96
+ }
97
+ console . log (
98
+ ' ' + chalk . yellow ( sizeLabel ) +
99
+ ' ' + chalk . dim ( asset . folder + path . sep ) + chalk . cyan ( asset . name )
100
+ ) ;
101
+ } ) ;
86
102
console . log ( ) ;
87
- console . log ( ' npm install -g pushstate-server' ) ;
88
- console . log ( ' pushstate-server build' ) ;
89
- console . log ( ' ' + openCommand + ' http://localhost:9000' ) ;
103
+
104
+ var openCommand = process . platform === 'win32' ? 'start' : 'open' ;
105
+ var homepagePath = require ( paths . appPackageJson ) . homepage ;
106
+ if ( homepagePath ) {
107
+ console . log ( 'You can now publish them at ' + homepagePath + '.' ) ;
108
+ console . log ( 'For example, if you use GitHub Pages:' ) ;
109
+ console . log ( ) ;
110
+ console . log ( ' git commit -am "Save local changes"' ) ;
111
+ console . log ( ' git checkout -B gh-pages' ) ;
112
+ console . log ( ' git add -f build' ) ;
113
+ console . log ( ' git commit -am "Rebuild website"' ) ;
114
+ console . log ( ' git filter-branch -f --prune-empty --subdirectory-filter build' ) ;
115
+ console . log ( ' git push -f origin gh-pages' ) ;
116
+ console . log ( ' git checkout -' ) ;
117
+ console . log ( ) ;
118
+ } else {
119
+ console . log ( 'You can now serve them with any static server.' ) ;
120
+ console . log ( 'For example:' ) ;
121
+ console . log ( ) ;
122
+ console . log ( ' npm install -g pushstate-server' ) ;
123
+ console . log ( ' pushstate-server build' ) ;
124
+ console . log ( ' ' + openCommand + ' http://localhost:9000' ) ;
125
+ console . log ( ) ;
126
+ console . log ( chalk . dim ( 'The project was built assuming it is hosted at the root.' ) ) ;
127
+ console . log ( chalk . dim ( 'Set the "homepage" field in package.json to override this.' ) ) ;
128
+ console . log ( chalk . dim ( 'For example, "homepage": "http://user.github.io/project".' ) ) ;
129
+ }
90
130
console . log ( ) ;
91
- console . log ( chalk . dim ( 'The project was built assuming it is hosted at the root.' ) ) ;
92
- console . log ( chalk . dim ( 'Set the "homepage" field in package.json to override this.' ) ) ;
93
- console . log ( chalk . dim ( 'For example, "homepage": "http://user.github.io/project".' ) ) ;
94
- }
95
- console . log ( ) ;
96
- } ) ;
131
+ } ) ;
132
+ }
0 commit comments