@@ -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' ) ;
17
19
const paths = require ( './paths' ) ;
18
20
const getClientEnvironment = require ( './env' ) ;
19
21
20
22
// Webpack uses `publicPath` to determine where the app is being served from.
21
23
// It requires a trailing slash, or the file assets will get an incorrect path.
22
24
const publicPath = paths . servedPath ;
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 === './' ;
25
+
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,40 +36,14 @@ 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
- // 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
- : { } ;
39
+ const cssThemeExtracts = feBrary . themes . map ( theme => {
40
+ // Note: defined here because it will be used more than once.
41
+ const filename = `${ theme } .css` ;
50
42
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
- } ;
43
+ return new ExtractTextPlugin ( {
44
+ filename,
45
+ } ) ;
46
+ } ) ;
73
47
74
48
// This is the production configuration.
75
49
// It compiles slowly and is focused on producing a fast and minimal bundle.
@@ -170,6 +144,65 @@ module.exports = {
170
144
] ,
171
145
include : paths . appSrc ,
172
146
} ,
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
+ ) ,
173
206
{
174
207
// "oneOf" will traverse all following loaders until one will
175
208
// match the requirements. When no loader matches it will fall
@@ -198,68 +231,6 @@ module.exports = {
198
231
compact : true ,
199
232
} ,
200
233
} ,
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
- } ,
263
234
// "file" loader makes sure assets end up in the `build` folder.
264
235
// When you `import` an asset, you get its filename.
265
236
// This loader doesn't use a "test" so it will catch all modules
@@ -270,7 +241,7 @@ module.exports = {
270
241
// it's runtime that would otherwise processed through "file" loader.
271
242
// Also exclude `html` and `json` extensions so they get processed
272
243
// by webpacks internal loaders.
273
- exclude : [ / \. ( j s | j s x | m j s ) $ / , / \. h t m l $ / , / \. j s o n $ / ] ,
244
+ exclude : [ / \. ( j s | j s x | m j s ) $ / , / \. h t m l $ / , / \. j s o n $ / , / \. c s s $ / ] ,
274
245
options : {
275
246
name : 'media/[name].[hash:8].[ext]' ,
276
247
} ,
@@ -288,9 +259,7 @@ module.exports = {
288
259
// Otherwise React will be compiled in the very slow development mode.
289
260
new webpack . DefinePlugin ( env . stringified ) ,
290
261
// Note: this won't work without ExtractTextPlugin.extract(..) in `loaders`.
291
- new ExtractTextPlugin ( {
292
- filename : cssFilename ,
293
- } ) ,
262
+ ...cssThemeExtracts ,
294
263
// Moment.js is an extremely popular library that bundles large locale files
295
264
// by default due to how Webpack interprets its code. This is a practical
296
265
// solution that requires the user to opt into importing specific locales.
0 commit comments