Skip to content

Commit 5544b7a

Browse files
committed
WIP themeing CSS for library build
1 parent 1830078 commit 5544b7a

File tree

1 file changed

+71
-102
lines changed

1 file changed

+71
-102
lines changed

packages/react-scripts/config/webpack.config.library.js

Lines changed: 71 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@ const ExtractTextPlugin = require('extract-text-webpack-plugin');
1414
const eslintFormatter = require('react-dev-utils/eslintFormatter');
1515
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
1616
const nodeExternals = require('webpack-node-externals');
17+
const feBrary = require('@domain-group/fe-brary');
18+
const generateCssConfig = require('./css');
1719
const paths = require('./paths');
1820
const getClientEnvironment = require('./env');
1921

2022
// Webpack uses `publicPath` to determine where the app is being served from.
2123
// It requires a trailing slash, or the file assets will get an incorrect path.
2224
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+
2626
// `publicUrl` is just like `publicPath`, but we will provide it to our app
2727
// as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript.
2828
// 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"') {
3636
throw new Error('Production builds must have NODE_ENV=production.');
3737
}
3838

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`;
5042

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+
});
7347

7448
// This is the production configuration.
7549
// It compiles slowly and is focused on producing a fast and minimal bundle.
@@ -170,6 +144,65 @@ module.exports = {
170144
],
171145
include: paths.appSrc,
172146
},
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: /legacy\.css$/,
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: /\.css$/,
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+
),
173206
{
174207
// "oneOf" will traverse all following loaders until one will
175208
// match the requirements. When no loader matches it will fall
@@ -198,68 +231,6 @@ module.exports = {
198231
compact: true,
199232
},
200233
},
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: /legacy\.css$/,
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: /\.css$/,
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-
},
263234
// "file" loader makes sure assets end up in the `build` folder.
264235
// When you `import` an asset, you get its filename.
265236
// This loader doesn't use a "test" so it will catch all modules
@@ -270,7 +241,7 @@ module.exports = {
270241
// it's runtime that would otherwise processed through "file" loader.
271242
// Also exclude `html` and `json` extensions so they get processed
272243
// by webpacks internal loaders.
273-
exclude: [/\.(js|jsx|mjs)$/, /\.html$/, /\.json$/],
244+
exclude: [/\.(js|jsx|mjs)$/, /\.html$/, /\.json$/, /\.css$/],
274245
options: {
275246
name: 'media/[name].[hash:8].[ext]',
276247
},
@@ -288,9 +259,7 @@ module.exports = {
288259
// Otherwise React will be compiled in the very slow development mode.
289260
new webpack.DefinePlugin(env.stringified),
290261
// Note: this won't work without ExtractTextPlugin.extract(..) in `loaders`.
291-
new ExtractTextPlugin({
292-
filename: cssFilename,
293-
}),
262+
...cssThemeExtracts,
294263
// Moment.js is an extremely popular library that bundles large locale files
295264
// by default due to how Webpack interprets its code. This is a practical
296265
// solution that requires the user to opt into importing specific locales.

0 commit comments

Comments
 (0)