@@ -14,15 +14,15 @@ const ExtractTextPlugin = require('extract-text-webpack-plugin');
14
14
const eslintFormatter = require ( 'react-dev-utils/eslintFormatter' ) ;
15
15
const ModuleScopePlugin = require ( 'react-dev-utils/ModuleScopePlugin' ) ;
16
16
const nodeExternals = require ( 'webpack-node-externals' ) ;
17
- const feBrary = require ( '@domain-group/fe-brary' ) ;
18
- const generateCssConfig = require ( './css' ) ;
19
17
const paths = require ( './paths' ) ;
20
18
const getClientEnvironment = require ( './env' ) ;
21
19
22
20
// Webpack uses `publicPath` to determine where the app is being served from.
23
21
// It requires a trailing slash, or the file assets will get an incorrect path.
24
22
const publicPath = paths . servedPath ;
25
-
23
+ // Some apps do not use client-side routing with pushState.
24
+ // For these, "homepage" can be set to "." to enable relative asset paths.
25
+ const shouldUseRelativeAssetPaths = publicPath === './' ;
26
26
// `publicUrl` is just like `publicPath`, but we will provide it to our app
27
27
// as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript.
28
28
// Omit trailing slash as %PUBLIC_URL%/xyz looks better than %PUBLIC_URL%xyz.
@@ -36,14 +36,40 @@ if (env.stringified['process.env'].NODE_ENV !== '"production"') {
36
36
throw new Error ( 'Production builds must have NODE_ENV=production.' ) ;
37
37
}
38
38
39
- const cssThemeExtracts = feBrary . themes . map ( theme => {
40
- // Note: defined here because it will be used more than once.
41
- const filename = `${ theme } .css` ;
39
+ // Note: defined here because it will be used more than once.
40
+ const cssFilename = 'styles.css' ;
41
+
42
+ // ExtractTextPlugin expects the build output to be flat.
43
+ // (See https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/27)
44
+ // However, our output is structured with css, js and media folders.
45
+ // To have this structure working with relative paths, we have to use custom options.
46
+ const extractTextPluginOptions = shouldUseRelativeAssetPaths
47
+ ? // Making sure that the publicPath goes back to to build folder.
48
+ { publicPath : Array ( cssFilename . split ( '/' ) . length ) . join ( '../' ) }
49
+ : { } ;
42
50
43
- return new ExtractTextPlugin ( {
44
- filename,
45
- } ) ;
46
- } ) ;
51
+ const postCSSLoaderOptions = {
52
+ ident : 'postcss' , // https://webpack.js.org/guides/migrating/#complex-options
53
+ plugins : loader => [
54
+ require ( 'postcss-flexbugs-fixes' ) ,
55
+ require ( 'postcss-import' ) ( { root : loader . resourcePath } ) ,
56
+ require ( 'postcss-cssnext' ) ( {
57
+ // postcss-cssnext passes `browsers` to multiple features, including autoprefixer
58
+ // https://github.com/MoOx/postcss-cssnext/blob/3.1.0/src/index.js#L29-L33
59
+ browsers : [
60
+ '>1%' ,
61
+ 'last 4 versions' ,
62
+ 'Firefox ESR' ,
63
+ 'not ie < 9' , // React doesn't support IE8 anyway
64
+ ] ,
65
+ features : {
66
+ autoprefixer : {
67
+ flexbox : 'no-2009' ,
68
+ } ,
69
+ } ,
70
+ } ) ,
71
+ ] ,
72
+ } ;
47
73
48
74
// This is the production configuration.
49
75
// It compiles slowly and is focused on producing a fast and minimal bundle.
@@ -144,65 +170,6 @@ module.exports = {
144
170
] ,
145
171
include : paths . appSrc ,
146
172
} ,
147
- ...cssThemeExtracts . reduce (
148
- ( accumulator , themeExtractTextPlugin , index ) => {
149
- return accumulator . concat (
150
- // The notation here is somewhat confusing.
151
- // "postcss" loader applies autoprefixer to our CSS.
152
- // "css" loader resolves paths in CSS and adds assets as dependencies.
153
- // "style" loader normally turns CSS into JS modules injecting <style>,
154
- // but unlike in development configuration, we do something different.
155
- // `ExtractTextPlugin` first applies the "postcss" and "css" loaders
156
- // (second argument), then grabs the result CSS and puts it into a
157
- // separate file in our build process. This way we actually ship
158
- // a single CSS file in production instead of JS code injecting <style>
159
- // tags. If you use code splitting, however, any async bundles will still
160
- // use the "style" loader inside the async code so CSS from them won't be
161
- // in the main CSS file.
162
- {
163
- test : / l e g a c y \. c s s $ / ,
164
- loader : themeExtractTextPlugin . extract ( {
165
- use : [
166
- {
167
- loader : require . resolve ( 'css-loader' ) ,
168
- options : {
169
- importLoaders : 1 ,
170
- minimize : true ,
171
- } ,
172
- } ,
173
- {
174
- loader : require . resolve ( 'postcss-loader' ) ,
175
- options : generateCssConfig ( feBrary . themes [ index ] ) ,
176
- } ,
177
- ] ,
178
- } ) ,
179
- // Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
180
- } ,
181
- {
182
- test : / \. c s s $ / ,
183
- loader : themeExtractTextPlugin . extract ( {
184
- use : [
185
- {
186
- loader : require . resolve ( 'css-loader' ) ,
187
- options : {
188
- minimize : true ,
189
- importLoaders : 1 ,
190
- modules : true ,
191
- localIdentName : '_[hash:base64:4]' ,
192
- } ,
193
- } ,
194
- {
195
- loader : require . resolve ( 'postcss-loader' ) ,
196
- options : generateCssConfig ( feBrary . themes [ index ] ) ,
197
- } ,
198
- ] ,
199
- } ) ,
200
- // Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
201
- }
202
- ) ;
203
- } ,
204
- [ ]
205
- ) ,
206
173
{
207
174
// "oneOf" will traverse all following loaders until one will
208
175
// match the requirements. When no loader matches it will fall
@@ -231,6 +198,68 @@ module.exports = {
231
198
compact : true ,
232
199
} ,
233
200
} ,
201
+ // The notation here is somewhat confusing.
202
+ // "postcss" loader applies autoprefixer to our CSS.
203
+ // "css" loader resolves paths in CSS and adds assets as dependencies.
204
+ // "style" loader normally turns CSS into JS modules injecting <style>,
205
+ // but unlike in development configuration, we do something different.
206
+ // `ExtractTextPlugin` first applies the "postcss" and "css" loaders
207
+ // (second argument), then grabs the result CSS and puts it into a
208
+ // separate file in our build process. This way we actually ship
209
+ // a single CSS file in production instead of JS code injecting <style>
210
+ // tags. If you use code splitting, however, any async bundles will still
211
+ // use the "style" loader inside the async code so CSS from them won't be
212
+ // in the main CSS file.
213
+ {
214
+ test : / l e g a c y \. c s s $ / ,
215
+ loader : ExtractTextPlugin . extract (
216
+ Object . assign (
217
+ {
218
+ use : [
219
+ {
220
+ loader : require . resolve ( 'css-loader' ) ,
221
+ options : {
222
+ importLoaders : 1 ,
223
+ minimize : true ,
224
+ } ,
225
+ } ,
226
+ {
227
+ loader : require . resolve ( 'postcss-loader' ) ,
228
+ options : postCSSLoaderOptions ,
229
+ } ,
230
+ ] ,
231
+ } ,
232
+ extractTextPluginOptions
233
+ )
234
+ ) ,
235
+ // Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
236
+ } ,
237
+ {
238
+ test : / \. c s s $ / ,
239
+ loader : ExtractTextPlugin . extract (
240
+ Object . assign (
241
+ {
242
+ use : [
243
+ {
244
+ loader : require . resolve ( 'css-loader' ) ,
245
+ options : {
246
+ minimize : true ,
247
+ importLoaders : 1 ,
248
+ modules : true ,
249
+ localIdentName : '_[hash:base64:4]' ,
250
+ } ,
251
+ } ,
252
+ {
253
+ loader : require . resolve ( 'postcss-loader' ) ,
254
+ options : postCSSLoaderOptions ,
255
+ } ,
256
+ ] ,
257
+ } ,
258
+ extractTextPluginOptions
259
+ )
260
+ ) ,
261
+ // Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
262
+ } ,
234
263
// "file" loader makes sure assets end up in the `build` folder.
235
264
// When you `import` an asset, you get its filename.
236
265
// This loader doesn't use a "test" so it will catch all modules
@@ -241,7 +270,7 @@ module.exports = {
241
270
// it's runtime that would otherwise processed through "file" loader.
242
271
// Also exclude `html` and `json` extensions so they get processed
243
272
// by webpacks internal loaders.
244
- exclude : [ / \. ( j s | j s x | m j s ) $ / , / \. h t m l $ / , / \. j s o n $ / , / \. c s s $ / ] ,
273
+ exclude : [ / \. ( j s | j s x | m j s ) $ / , / \. h t m l $ / , / \. j s o n $ / ] ,
245
274
options : {
246
275
name : 'media/[name].[hash:8].[ext]' ,
247
276
} ,
@@ -259,7 +288,9 @@ module.exports = {
259
288
// Otherwise React will be compiled in the very slow development mode.
260
289
new webpack . DefinePlugin ( env . stringified ) ,
261
290
// Note: this won't work without ExtractTextPlugin.extract(..) in `loaders`.
262
- ...cssThemeExtracts ,
291
+ new ExtractTextPlugin ( {
292
+ filename : cssFilename ,
293
+ } ) ,
263
294
// Moment.js is an extremely popular library that bundles large locale files
264
295
// by default due to how Webpack interprets its code. This is a practical
265
296
// solution that requires the user to opt into importing specific locales.
0 commit comments