@@ -3,50 +3,99 @@ const path = require('path');
3
3
const ExtractTextPlugin = require ( 'extract-text-webpack-plugin' ) ;
4
4
const Clean = require ( 'clean-webpack-plugin' ) ;
5
5
const HtmlWebpackPlugin = require ( 'html-webpack-plugin' ) ;
6
+ const ChunkManifestPlugin = require ( 'chunk-manifest-webpack-plugin' ) ;
7
+ const ScriptExtHtmlWebpackPlugin = require ( 'script-ext-html-webpack-plugin' ) ;
8
+ const WebpackChunkHash = require ( 'webpack-chunk-hash' ) ;
6
9
7
- const SRC_PATH = 'src' ;
8
- const SRC_ABSOLUTE_PATH = path . join ( __dirname , SRC_PATH ) ;
9
- const INDEX_HTML_TEMPLATE_ABSOLUTE_PATH = path . join ( SRC_ABSOLUTE_PATH , 'index.html' ) ;
10
+ function addVendorSplitting ( plugins ) {
11
+ return [
12
+ new webpack . optimize . CommonsChunkPlugin ( {
13
+ name : 'vendor' ,
14
+ minChunks ( module ) {
15
+ return module . context && module . context . indexOf ( 'node_modules' ) >= 0 ;
16
+ }
17
+ } ) ,
18
+ new webpack . optimize . CommonsChunkPlugin ( {
19
+ name : 'manifest' ,
20
+ minChunks : Infinity
21
+ } ) ,
22
+ new webpack . HashedModuleIdsPlugin ( ) ,
23
+ new WebpackChunkHash ( ) ,
24
+ new ChunkManifestPlugin ( {
25
+ filename : 'chunk-manifest.json' ,
26
+ manifestVariable : 'webpackManifest' ,
27
+ inlineManifest : true
28
+ } ) ,
29
+ ...plugins ,
30
+ new ScriptExtHtmlWebpackPlugin ( {
31
+ inline : 'manifest'
32
+ } )
33
+ ] ;
34
+ }
10
35
11
- const DIST_PATH = 'dist' ;
12
- const DIST_ABSOLUTE_PATH = path . join ( __dirname , DIST_PATH ) ;
36
+ function addProductionPlugins ( plugins ) {
37
+ // https://webpack.js.org/guides/production-build/
13
38
14
- const APPLICATION_BUNDLE_FILENAME = 'app-[hash].js' ;
15
- const CSS_BUNDLE_FILENAME = 'app-[hash].css' ;
16
-
17
- const plugins = [
18
- new ExtractTextPlugin ( {
19
- filename : CSS_BUNDLE_FILENAME ,
20
- disable : false ,
21
- allChunks : true
22
- } ) ,
23
- new Clean ( [ DIST_PATH ] ) ,
24
- new HtmlWebpackPlugin ( {
25
- template : INDEX_HTML_TEMPLATE_ABSOLUTE_PATH ,
26
- inject : 'body'
27
- } )
28
- ] ;
29
-
30
- module . exports = ( env ) => {
31
- if ( env && env . dist ) {
32
- // https://webpack.js.org/guides/production-build/
33
- plugins . push ( new webpack . optimize . UglifyJsPlugin ( {
39
+ return [
40
+ ...plugins ,
41
+ new webpack . optimize . UglifyJsPlugin ( {
34
42
beautify : false ,
35
43
mangle : true ,
36
44
comments : false
37
- } ) ) ;
38
-
39
- plugins . push ( new webpack . DefinePlugin ( {
45
+ } ) ,
46
+ new webpack . DefinePlugin ( {
40
47
'process.env.NODE_ENV' : JSON . stringify ( 'production' )
41
- } ) ) ;
48
+ } )
49
+ ] ;
50
+ }
51
+
52
+ module . exports = ( env ) => {
53
+ const SRC_PATH = 'src' ;
54
+ const SRC_ABSOLUTE_PATH = path . join ( __dirname , SRC_PATH ) ;
55
+ const INDEX_HTML_TEMPLATE_ABSOLUTE_PATH = path . join ( SRC_ABSOLUTE_PATH , 'index.html' ) ;
56
+
57
+ const DIST_PATH = 'dist' ;
58
+ const DIST_ABSOLUTE_PATH = path . join ( __dirname , DIST_PATH ) ;
59
+
60
+ // from documentation: Don’t use [chunkhash] in development since this will increase compilation time
61
+ // https://webpack.js.org/guides/caching/
62
+ const FILE_PATTERN_DEVELOPMENT = '[name]' ;
63
+ const FILE_PATTERN_PRODUCTION = '[name]-[chunkhash]' ;
64
+
65
+ let applicationBundleFilename = `${ FILE_PATTERN_DEVELOPMENT } .js` ;
66
+ let cssBundleFilename = `${ FILE_PATTERN_DEVELOPMENT } .css` ;
67
+
68
+ const IS_PRODUCTION = env && env . production ;
69
+
70
+ if ( IS_PRODUCTION ) {
71
+ applicationBundleFilename = `${ FILE_PATTERN_PRODUCTION } .js` ;
72
+ cssBundleFilename = `${ FILE_PATTERN_PRODUCTION } .css` ;
73
+ }
74
+
75
+ let plugins = [
76
+ new ExtractTextPlugin ( {
77
+ filename : cssBundleFilename ,
78
+ disable : false ,
79
+ allChunks : true
80
+ } ) ,
81
+ new Clean ( [ DIST_PATH ] ) ,
82
+ new HtmlWebpackPlugin ( {
83
+ template : INDEX_HTML_TEMPLATE_ABSOLUTE_PATH
84
+ } )
85
+ ] ;
86
+
87
+ if ( IS_PRODUCTION ) {
88
+ // don't use it in development to save time on recompile
89
+ plugins = addVendorSplitting ( plugins ) ;
90
+ plugins = addProductionPlugins ( plugins ) ;
42
91
}
43
92
44
93
return {
45
94
context : SRC_ABSOLUTE_PATH ,
46
95
entry : './entry' ,
47
96
output : {
48
97
path : DIST_ABSOLUTE_PATH ,
49
- filename : APPLICATION_BUNDLE_FILENAME
98
+ filename : applicationBundleFilename
50
99
} ,
51
100
module : {
52
101
// loaders are loaded from bottom to top
@@ -70,7 +119,7 @@ module.exports = (env) => {
70
119
include : SRC_ABSOLUTE_PATH , // other paths are ignored
71
120
use : ExtractTextPlugin . extract ( {
72
121
fallback : 'style-loader' ,
73
- use : ' css-loader? minimize!sass-loader'
122
+ use : ` css-loader${ IS_PRODUCTION ? '? minimize' : '' } !sass-loader`
74
123
} )
75
124
} , {
76
125
test : / \. ( j p e ? g | p n g | g i f | s v g ) $ / ,
@@ -90,13 +139,13 @@ module.exports = (env) => {
90
139
contentBase : DIST_PATH ,
91
140
host : '0.0.0.0' ,
92
141
// proxy requests to the backend
93
- // TODO: this setting doesn't work with " historyApiFallback: true"
142
+ // TODO: this setting doesn't work with ' historyApiFallback: true'
94
143
// proxy: {
95
144
// '*': 'http://localhost'
96
145
// },
97
146
98
147
// this setting is needed to support react-router
99
- // TODO: this setting doesn't work with " proxy"
148
+ // TODO: this setting doesn't work with ' proxy'
100
149
historyApiFallback : true
101
150
}
102
151
} ;
0 commit comments