@@ -5,6 +5,9 @@ const path = require('path');
5
5
const webpack = require ( 'webpack' ) ;
6
6
const CaseSensitivePathsPlugin = require ( 'case-sensitive-paths-webpack-plugin' ) ;
7
7
const WatchMissingNodeModulesPlugin = require ( 'react-dev-utils/WatchMissingNodeModulesPlugin' ) ;
8
+ const ExtractTextPlugin = require ( 'extract-text-webpack-plugin' ) ;
9
+ const ManifestPlugin = require ( 'webpack-manifest-plugin' ) ;
10
+ const SWPrecacheWebpackPlugin = require ( 'sw-precache-webpack-plugin' ) ;
8
11
const eslintFormatter = require ( 'react-dev-utils/eslintFormatter' ) ;
9
12
const ModuleScopePlugin = require ( 'react-dev-utils/ModuleScopePlugin' ) ;
10
13
const getClientEnvironment = require ( './env' ) ;
@@ -20,26 +23,149 @@ const publicUrl = '';
20
23
// Get environment variables to inject into our app.
21
24
const env = getClientEnvironment ( publicUrl ) ;
22
25
26
+ // Note: defined here because it will be used more than once.
27
+ const cssFilename = 'css/[name].css' ;
28
+
29
+ const isProd = env . stringified [ 'process.env' ] . NODE_ENV === '"production"' ;
30
+
31
+ function getPlugins ( ) {
32
+ let plugins = [ ] ;
33
+
34
+ // Add module names to factory functions so they appear in browser profiler.
35
+ ! isProd && plugins . push ( new webpack . NamedModulesPlugin ( ) ) ;
36
+
37
+ // Makes some environment variables available to the JS code, for example:
38
+ // if (process.env.NODE_ENV === 'development') { ... }. See `./env.js`.
39
+ plugins . push ( new webpack . DefinePlugin ( env . stringified ) ) ;
40
+
41
+ // This is necessary to emit hot updates (currently CSS only):
42
+ ! isProd && plugins . push ( new webpack . HotModuleReplacementPlugin ( ) ) ;
43
+
44
+ // Watcher doesn't work well if you mistype casing in a path so we use
45
+ // a plugin that prints an error when you attempt to do this.
46
+ // See https://github.com/facebookincubator/create-react-app/issues/240
47
+ ! isProd && plugins . push ( new CaseSensitivePathsPlugin ( ) ) ;
48
+
49
+ // If you require a missing module and then `npm install` it, you still have
50
+ // to restart the development server for Webpack to discover it. This plugin
51
+ // makes the discovery automatic so you don't have to restart.
52
+ // See https://github.com/facebookincubator/create-react-app/issues/186
53
+ ! isProd && plugins . push ( new WatchMissingNodeModulesPlugin ( paths . appNodeModules ) ) ;
54
+
55
+ // optimize out highlight.js languages we dont need
56
+ plugins . push (
57
+ new webpack . ContextReplacementPlugin (
58
+ / h i g h l i g h t \. j s \/ l i b \/ l a n g u a g e s $ / ,
59
+ new RegExp ( `^./(${ [ 'diff' ] . join ( '|' ) } )$` )
60
+ )
61
+ ) ;
62
+
63
+ // Moment.js is an extremely popular library that bundles large locale files
64
+ // by default due to how Webpack interprets its code. This is a practical
65
+ // solution that requires the user to opt into importing specific locales.
66
+ // https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
67
+ // You can remove this if you don't use Moment.js:
68
+ plugins . push ( new webpack . IgnorePlugin ( / ^ \. \/ l o c a l e $ / , / m o m e n t $ / ) ) ;
69
+
70
+ // Note: this won't work without ExtractTextPlugin.extract(..) in `loaders`.
71
+ plugins . push (
72
+ new ExtractTextPlugin ( {
73
+ filename : cssFilename
74
+ } )
75
+ ) ;
76
+
77
+ // Generate a manifest file which contains a mapping of all asset filenames
78
+ // to their corresponding output file so that tools can pick it up without
79
+ // having to parse `index.html`.
80
+ isProd &&
81
+ plugins . push (
82
+ new ManifestPlugin ( {
83
+ fileName : 'asset-manifest.json'
84
+ } )
85
+ ) ;
86
+
87
+ // Generate a service worker script that will precache, and keep up to date,
88
+ // the HTML & assets that are part of the Webpack build.
89
+ isProd &&
90
+ plugins . push (
91
+ new SWPrecacheWebpackPlugin ( {
92
+ // By default, a cache-busting query parameter is appended to requests
93
+ // used to populate the caches, to ensure the responses are fresh.
94
+ // If a URL is already hashed by Webpack, then there is no concern
95
+ // about it being stale, and the cache-busting can be skipped.
96
+ dontCacheBustUrlsMatching : / \. \w { 8 } \. / ,
97
+ filename : 'service-worker.js' ,
98
+ logger ( message ) {
99
+ if ( message . indexOf ( 'Total precache size is' ) === 0 ) {
100
+ // This message occurs for every build and is a bit too noisy.
101
+ return ;
102
+ }
103
+ if ( message . indexOf ( 'Skipping static resource' ) === 0 ) {
104
+ // This message obscures real errors so we ignore it.
105
+ // https://github.com/facebookincubator/create-react-app/issues/2612
106
+ return ;
107
+ }
108
+ console . log ( message ) ;
109
+ } ,
110
+ minify : true ,
111
+ // For unknown URLs, fallback to the index page
112
+ navigateFallback : publicUrl + '/index.html' ,
113
+ // Ignores URLs starting from /__ (useful for Firebase):
114
+ // https://github.com/facebookincubator/create-react-app/issues/2237#issuecomment-302693219
115
+ navigateFallbackWhitelist : [ / ^ (? ! \/ _ _ ) .* / ] ,
116
+ // Don't precache sourcemaps (they're large) and build asset manifest:
117
+ staticFileGlobsIgnorePatterns : [ / \. m a p $ / , / a s s e t - m a n i f e s t \. j s o n $ / ]
118
+ } )
119
+ ) ;
120
+
121
+ // Minify the code.
122
+ isProd &&
123
+ plugins . push (
124
+ new webpack . optimize . UglifyJsPlugin ( {
125
+ compress : {
126
+ warnings : false ,
127
+ // Disabled because of an issue with Uglify breaking seemingly valid code:
128
+ // https://github.com/facebookincubator/create-react-app/issues/2376
129
+ // Pending further investigation:
130
+ // https://github.com/mishoo/UglifyJS2/issues/2011
131
+ comparisons : false
132
+ } ,
133
+ output : {
134
+ comments : false ,
135
+ // Turned on because emoji and regex is not minified properly using default
136
+ // https://github.com/facebookincubator/create-react-app/issues/2488
137
+ ascii_only : true
138
+ } ,
139
+ sourceMap : true
140
+ } )
141
+ ) ;
142
+ return plugins ;
143
+ }
144
+
145
+ function getEntry ( ) {
146
+ let entry = [ ] ;
147
+ // We ship a few polyfills by default:
148
+ entry . push ( require . resolve ( './polyfills' ) ) ;
149
+ // Errors should be considered fatal in development
150
+ ! isProd && entry . push ( require . resolve ( 'react-error-overlay' ) ) ;
151
+ // Finally, this is your app's code:
152
+ // We include the app code last so that if there is a runtime error during
153
+ // initialization
154
+ entry . push ( paths . appIndexJs ) ;
155
+ return entry ;
156
+ }
157
+
23
158
// This is the development configuration.
24
159
// It is focused on developer experience and fast rebuilds.
25
160
// The production configuration is different and lives in a separate file.
26
161
module . exports = {
27
162
// You may want 'eval' instead if you prefer to see the compiled output in DevTools.
28
163
// See the discussion in https://github.com/facebookincubator/create-react-app/issues/343.
29
- devtool : 'cheap-module-source-map' ,
164
+ devtool : isProd ? 'source-map' : 'cheap-module-source-map' ,
30
165
// These are the "entry points" to our application.
31
166
// This means they will be the "root" imports that are included in JS bundle.
32
167
// The first two entry points enable "hot" CSS and auto-refreshes for JS.
33
- entry : [
34
- // We ship a few polyfills by default:
35
- require . resolve ( './polyfills' ) ,
36
- // Errors should be considered fatal in development
37
- require . resolve ( 'react-error-overlay' ) ,
38
- // Finally, this is your app's code:
39
- paths . appIndexJs
40
- // We include the app code last so that if there is a runtime error during
41
- // initialization
42
- ] ,
168
+ entry : getEntry ( ) ,
43
169
output : {
44
170
// Next line is not used in dev but WebpackDevServer crashes without it:
45
171
path : paths . appBuild ,
@@ -131,7 +257,7 @@ module.exports = {
131
257
] ,
132
258
loader : require . resolve ( 'file-loader' ) ,
133
259
options : {
134
- name : 'media/[name].[hash:8].[ ext]'
260
+ name : 'media/[name].[ext]'
135
261
}
136
262
} ,
137
263
// "url" loader works like "file" loader except that it embeds assets
@@ -142,7 +268,7 @@ module.exports = {
142
268
loader : require . resolve ( 'url-loader' ) ,
143
269
options : {
144
270
limit : 10000 ,
145
- name : 'media/[name].[hash:8].[ ext]'
271
+ name : 'media/[name].[ext]'
146
272
}
147
273
} ,
148
274
// Process JS with Babel.
@@ -154,7 +280,8 @@ module.exports = {
154
280
// This is a feature of `babel-loader` for webpack (not Babel itself).
155
281
// It enables caching results in ./node_modules/.cache/babel-loader/
156
282
// directory for faster rebuilds.
157
- cacheDirectory : true
283
+ cacheDirectory : ! isProd ,
284
+ compact : isProd
158
285
}
159
286
} ,
160
287
// "postcss" loader applies autoprefixer to our CSS.
@@ -198,35 +325,7 @@ module.exports = {
198
325
// Remember to add the new extension(s) to the "file" loader exclusion list.
199
326
]
200
327
} ,
201
- plugins : [
202
- // Add module names to factory functions so they appear in browser profiler.
203
- new webpack . NamedModulesPlugin ( ) ,
204
- // Makes some environment variables available to the JS code, for example:
205
- // if (process.env.NODE_ENV === 'development') { ... }. See `./env.js`.
206
- new webpack . DefinePlugin ( env . stringified ) ,
207
- // This is necessary to emit hot updates (currently CSS only):
208
- new webpack . HotModuleReplacementPlugin ( ) ,
209
- // Watcher doesn't work well if you mistype casing in a path so we use
210
- // a plugin that prints an error when you attempt to do this.
211
- // See https://github.com/facebookincubator/create-react-app/issues/240
212
- new CaseSensitivePathsPlugin ( ) ,
213
- // If you require a missing module and then `npm install` it, you still have
214
- // to restart the development server for Webpack to discover it. This plugin
215
- // makes the discovery automatic so you don't have to restart.
216
- // See https://github.com/facebookincubator/create-react-app/issues/186
217
- new WatchMissingNodeModulesPlugin ( paths . appNodeModules ) ,
218
- // Moment.js is an extremely popular library that bundles large locale files
219
- // by default due to how Webpack interprets its code. This is a practical
220
- // solution that requires the user to opt into importing specific locales.
221
- // https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
222
- // You can remove this if you don't use Moment.js:
223
- new webpack . IgnorePlugin ( / ^ \. \/ l o c a l e $ / , / m o m e n t $ / ) ,
224
- // optimize out highlight.js languages we dont need
225
- new webpack . ContextReplacementPlugin (
226
- / h i g h l i g h t \. j s \/ l i b \/ l a n g u a g e s $ / ,
227
- new RegExp ( `^./(${ [ 'diff' ] . join ( '|' ) } )$` )
228
- )
229
- ] ,
328
+ plugins : getPlugins ( ) ,
230
329
// Some libraries import Node modules but don't use them in the browser.
231
330
// Tell Webpack to provide empty mocks for them so importing them works.
232
331
node : {
@@ -239,6 +338,6 @@ module.exports = {
239
338
// splitting or minification in interest of speed. These warnings become
240
339
// cumbersome.
241
340
performance : {
242
- hints : false
341
+ hints : isProd
243
342
}
244
343
} ;
0 commit comments