@@ -18,6 +18,9 @@ const isDebug = !process.argv.includes('--release');
18
18
const isVerbose = process . argv . includes ( '--verbose' ) ;
19
19
const isAnalyze = process . argv . includes ( '--analyze' ) || process . argv . includes ( '--analyse' ) ;
20
20
21
+ const stylesRegExp = / \. ( c s s | l e s s | s c s s | s s s ) $ / ;
22
+ const staticAssetName = isDebug ? '[path][name].[ext]?[hash:8]' : '[hash:8].[ext]' ;
23
+
21
24
//
22
25
// Common configuration chunk to be used for both
23
26
// client-side (client.js) and server-side (server.js) bundles
@@ -42,14 +45,17 @@ const config = {
42
45
} ,
43
46
44
47
module : {
48
+ // Make missing exports an error instead of warning
49
+ strictExportPresence : true ,
50
+
45
51
rules : [
46
52
{
47
53
test : / \. j s x ? $ / ,
48
54
loader : 'babel-loader' ,
49
55
include : [
50
56
path . resolve ( __dirname , '../src' ) ,
51
57
] ,
52
- query : {
58
+ options : {
53
59
// https://github.com/babel/babel-loader#options
54
60
cacheDirectory : isDebug ,
55
61
@@ -87,8 +93,14 @@ const config = {
87
93
] ,
88
94
} ,
89
95
} ,
96
+
97
+ // Handle internal/project styles (from src folder)
90
98
{
91
- test : / \. c s s / ,
99
+ // Internal Styles
100
+ test : stylesRegExp ,
101
+ include : [
102
+ path . resolve ( __dirname , '../src' ) ,
103
+ ] ,
92
104
use : [
93
105
{
94
106
loader : 'isomorphic-style-loader' ,
@@ -109,6 +121,8 @@ const config = {
109
121
} ,
110
122
] ,
111
123
} ,
124
+
125
+ // Handle external/third-party styles (from node_modules)
112
126
{
113
127
test : / t h e m e .s c s s $ / ,
114
128
loaders : [
@@ -118,7 +132,7 @@ const config = {
118
132
] ,
119
133
} ,
120
134
{
121
- test : / \. s c s s $ / ,
135
+ test : stylesRegExp ,
122
136
exclude : [ / t h e m e .s c s s $ / ] ,
123
137
use : [
124
138
'isomorphic-style-loader' ,
@@ -128,26 +142,62 @@ const config = {
128
142
] ,
129
143
} ,
130
144
{
131
- test : / \. m d $ / ,
132
- loader : path . resolve ( __dirname , './lib/markdown-loader.js' ) ,
145
+ test : / \. ( b m p | g i f | j p e ? g | p n g ) $ / ,
146
+ issuer : stylesRegExp ,
147
+ loader : 'url-loader' ,
148
+ options : {
149
+ name : staticAssetName ,
150
+ limit : 4096 , // 4kb
151
+ } ,
133
152
} ,
153
+
154
+ // Inline small SVGs into CSS as UTF-8 encoded DataUrl string
134
155
{
135
- test : / \. t x t $ / ,
136
- loader : 'raw-loader' ,
156
+ test : / \. s v g $ / ,
157
+ issuer : stylesRegExp ,
158
+ loader : 'svg-url-loader' ,
159
+ options : {
160
+ name : staticAssetName ,
161
+ limit : 4096 , // 4kb
162
+ } ,
137
163
} ,
164
+
165
+ // Return public URL to large images otherwise
138
166
{
139
- test : / \. ( i c o | j p g | j p e g | p n g | g i f | e o t | o t f | w e b p | s v g | t t f | w o f f | w o f f 2 ) ( \? .* ) ? $ / ,
167
+ test : / \. ( b m p | g i f | j p e ? g | p n g | s v g ) $ / ,
168
+ issuer : { not : [ stylesRegExp ] } ,
140
169
loader : 'file-loader' ,
141
- query : {
142
- name : isDebug ? '[path][name].[ext]?[hash:8]' : '[hash:8].[ext]' ,
170
+ options : {
171
+ name : staticAssetName ,
143
172
} ,
144
173
} ,
174
+
175
+ // Convert plain text into module
145
176
{
146
- test : / \. ( m p 4 | w e b m | w a v | m p 3 | m 4 a | a a c | o g a ) ( \? .* ) ? $ / ,
147
- loader : 'url-loader' ,
148
- query : {
149
- name : isDebug ? '[path][name].[ext]?[hash:8]' : '[hash:8].[ext]' ,
150
- limit : 10000 ,
177
+ test : / \. t x t $ / ,
178
+ loader : 'raw-loader' ,
179
+ } ,
180
+
181
+ // Convert markdown into html
182
+ {
183
+ test : / \. m d $ / ,
184
+ loader : path . resolve ( __dirname , './lib/markdown-loader.js' ) ,
185
+ } ,
186
+
187
+ // Return public URL for all assets unless explicitly excluded
188
+ // DO NOT FORGET to update `exclude` list when you adding a new loader
189
+ {
190
+ exclude : [
191
+ / \. j s x ? $ / ,
192
+ / \. j s o n $ / ,
193
+ stylesRegExp ,
194
+ / \. ( b m p | g i f | j p e ? g | p n g | s v g ) $ / ,
195
+ / \. t x t $ / ,
196
+ / \. m d $ / ,
197
+ ] ,
198
+ loader : 'file-loader' ,
199
+ options : {
200
+ name : staticAssetName ,
151
201
} ,
152
202
} ,
153
203
@@ -166,16 +216,19 @@ const config = {
166
216
167
217
cache : isDebug ,
168
218
219
+ // Specify what bundle information gets displayed
220
+ // https://webpack.js.org/configuration/stats/
169
221
stats : {
222
+ cached : isVerbose ,
223
+ cachedAssets : isVerbose ,
224
+ chunks : isVerbose ,
225
+ chunkModules : isVerbose ,
170
226
colors : true ,
171
- reasons : isDebug ,
172
227
hash : isVerbose ,
173
- version : isVerbose ,
228
+ modules : isVerbose ,
229
+ reasons : isDebug ,
174
230
timings : true ,
175
- chunks : isVerbose ,
176
- chunkModules : isVerbose ,
177
- cached : isVerbose ,
178
- cachedAssets : isVerbose ,
231
+ version : isVerbose ,
179
232
} ,
180
233
181
234
// Choose a developer tool to enhance debugging
@@ -222,6 +275,10 @@ const clientConfig = {
222
275
} ) ,
223
276
224
277
...isDebug ? [ ] : [
278
+ // Decrease script evaluation time
279
+ // https://github.com/webpack/webpack/blob/master/examples/scope-hoisting/README.md
280
+ new webpack . optimize . ModuleConcatenationPlugin ( ) ,
281
+
225
282
// Minimize all JavaScript output of chunks
226
283
// https://github.com/mishoo/UglifyJS2#compressor-options
227
284
new webpack . optimize . UglifyJsPlugin ( {
@@ -280,6 +337,12 @@ const serverConfig = {
280
337
libraryTarget : 'commonjs2' ,
281
338
} ,
282
339
340
+ // Webpack mutates resolve object, so clone it to avoid issues
341
+ // https://github.com/webpack/webpack/issues/4817
342
+ resolve : {
343
+ ...config . resolve ,
344
+ } ,
345
+
283
346
module : {
284
347
...config . module ,
285
348
@@ -288,9 +351,9 @@ const serverConfig = {
288
351
if ( rule . loader === 'babel-loader' ) {
289
352
return {
290
353
...rule ,
291
- query : {
292
- ...rule . query ,
293
- presets : rule . query . presets . map ( preset => ( preset [ 0 ] !== 'env' ? preset : [ 'env' , {
354
+ options : {
355
+ ...rule . options ,
356
+ presets : rule . options . presets . map ( preset => ( preset [ 0 ] !== 'env' ? preset : [ 'env' , {
294
357
targets : {
295
358
node : pkg . engines . node . match ( / ( \d + \. ? ) + / ) [ 0 ] ,
296
359
} ,
@@ -302,12 +365,12 @@ const serverConfig = {
302
365
} ;
303
366
}
304
367
305
- if ( rule . loader === 'file-loader' || rule . loader === 'url-loader' ) {
368
+ if ( rule . loader === 'file-loader' || rule . loader === 'url-loader' || rule . loader === 'svg-url-loader' ) {
306
369
return {
307
370
...rule ,
308
- query : {
309
- ...rule . query ,
310
- name : `public/assets/${ rule . query . name } ` ,
371
+ options : {
372
+ ...rule . options ,
373
+ name : `public/assets/${ rule . options . name } ` ,
311
374
publicPath : url => url . replace ( / ^ p u b l i c / , '' ) ,
312
375
} ,
313
376
} ;
@@ -321,7 +384,7 @@ const serverConfig = {
321
384
'./assets.json' ,
322
385
nodeExternals ( {
323
386
whitelist : [
324
- / \. ( c s s | l e s s | s c s s | s s s ) $ / i ,
387
+ stylesRegExp ,
325
388
] ,
326
389
} ) ,
327
390
] ,
0 commit comments