From 0b9105ec737509e3e0e714bd84e51f95f78aa43b Mon Sep 17 00:00:00 2001 From: John Coburn Date: Fri, 21 Jan 2022 10:49:28 -0600 Subject: [PATCH 1/3] add custom postcss plugin --- .../node_modules/@folio/app1/icons/app.png | 0 .../node_modules/@folio/app1/icons/app.svg | 0 .../node_modules/@folio/app1/package.json | 29 ---- .../node_modules/@folio/app2/icons/app.svg | 0 .../@folio/stripes-dep1/icons/thing.png | 0 .../@folio/stripes-dep1/icons/thing.svg | 0 .../@folio/stripes-dep1/package.json | 14 -- .../node_modules/@folio/app2/package.json | 25 ---- .../@folio/stripes-dep1/icons/otherthing.png | 0 .../@folio/stripes-dep1/icons/otherthing.svg | 0 .../@folio/stripes-dep1/icons/thing.png | 0 .../@folio/stripes-dep1/icons/thing.svg | 0 .../@folio/stripes-dep1/package.json | 19 --- .../@notfolio/stripes-dep2/package.json | 5 - webpack.config.base.js | 1 - webpack.config.cli.dev.js | 66 +-------- webpack.config.css.js | 102 ++++++++++++++ webpack/postcss/postcss-omit-imports/index.js | 14 ++ .../postcss/postcss-omit-imports/omit.test.js | 133 ++++++++++++++++++ webpack/serve.js | 3 + 20 files changed, 258 insertions(+), 153 deletions(-) delete mode 100644 test/webpack/node_modules/@folio/app1/icons/app.png delete mode 100644 test/webpack/node_modules/@folio/app1/icons/app.svg delete mode 100644 test/webpack/node_modules/@folio/app1/package.json delete mode 100644 test/webpack/node_modules/@folio/app2/icons/app.svg delete mode 100644 test/webpack/node_modules/@folio/app2/node_modules/@folio/stripes-dep1/icons/thing.png delete mode 100644 test/webpack/node_modules/@folio/app2/node_modules/@folio/stripes-dep1/icons/thing.svg delete mode 100644 test/webpack/node_modules/@folio/app2/node_modules/@folio/stripes-dep1/package.json delete mode 100644 test/webpack/node_modules/@folio/app2/package.json delete mode 100644 test/webpack/node_modules/@folio/stripes-dep1/icons/otherthing.png delete mode 100644 test/webpack/node_modules/@folio/stripes-dep1/icons/otherthing.svg delete mode 100644 test/webpack/node_modules/@folio/stripes-dep1/icons/thing.png delete mode 100644 test/webpack/node_modules/@folio/stripes-dep1/icons/thing.svg delete mode 100644 test/webpack/node_modules/@folio/stripes-dep1/package.json delete mode 100644 test/webpack/node_modules/@notfolio/stripes-dep2/package.json create mode 100644 webpack.config.css.js create mode 100644 webpack/postcss/postcss-omit-imports/index.js create mode 100644 webpack/postcss/postcss-omit-imports/omit.test.js diff --git a/test/webpack/node_modules/@folio/app1/icons/app.png b/test/webpack/node_modules/@folio/app1/icons/app.png deleted file mode 100644 index e69de29..0000000 diff --git a/test/webpack/node_modules/@folio/app1/icons/app.svg b/test/webpack/node_modules/@folio/app1/icons/app.svg deleted file mode 100644 index e69de29..0000000 diff --git a/test/webpack/node_modules/@folio/app1/package.json b/test/webpack/node_modules/@folio/app1/package.json deleted file mode 100644 index 3f0601f..0000000 --- a/test/webpack/node_modules/@folio/app1/package.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "name": "@folio/app1", - "version": "1.2.3", - "main": "src/index.js", - "stripes": { - "actsAs": [ - "app", - "settings" - ], - "displayName": "ui-app1.meta.title", - "route": "/app1", - "actionNames": [ - "stripesHome", - "app1SortByName" - ], - "icons": [ - { - "name": "app", - "alt": "Create, view and manage app1", - "title": "Application 1" - } - ], - "okapiInterfaces": { - "users": "15.0", - "configuration": "2.0" - }, - "stripesDeps": ["@folio/stripes-dep1", "@notfolio/stripes-dep2"] - } -} diff --git a/test/webpack/node_modules/@folio/app2/icons/app.svg b/test/webpack/node_modules/@folio/app2/icons/app.svg deleted file mode 100644 index e69de29..0000000 diff --git a/test/webpack/node_modules/@folio/app2/node_modules/@folio/stripes-dep1/icons/thing.png b/test/webpack/node_modules/@folio/app2/node_modules/@folio/stripes-dep1/icons/thing.png deleted file mode 100644 index e69de29..0000000 diff --git a/test/webpack/node_modules/@folio/app2/node_modules/@folio/stripes-dep1/icons/thing.svg b/test/webpack/node_modules/@folio/app2/node_modules/@folio/stripes-dep1/icons/thing.svg deleted file mode 100644 index e69de29..0000000 diff --git a/test/webpack/node_modules/@folio/app2/node_modules/@folio/stripes-dep1/package.json b/test/webpack/node_modules/@folio/app2/node_modules/@folio/stripes-dep1/package.json deleted file mode 100644 index 8b3b7d1..0000000 --- a/test/webpack/node_modules/@folio/app2/node_modules/@folio/stripes-dep1/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "@folio/stripes-dep1", - "version": "1.2.3", - "main": "src/index.js", - "stripes": { - "icons": [ - { - "name": "thing", - "alt": "Do thing", - "title": "Thing" - } - ] - } -} diff --git a/test/webpack/node_modules/@folio/app2/package.json b/test/webpack/node_modules/@folio/app2/package.json deleted file mode 100644 index 6f00a55..0000000 --- a/test/webpack/node_modules/@folio/app2/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "@folio/app2", - "version": "1.2.3", - "main": "src/index.js", - "stripes": { - "actsAs": [ - "app", - "settings" - ], - "displayName": "ui-app2.meta.title", - "route": "/app2", - "icons": [ - { - "name": "app", - "alt": "Create, view and manage app2", - "title": "Application 2" - } - ], - "okapiInterfaces": { - "users": "15.0", - "configuration": "2.0" - }, - "stripesDeps": ["@folio/stripes-dep1"] - } -} diff --git a/test/webpack/node_modules/@folio/stripes-dep1/icons/otherthing.png b/test/webpack/node_modules/@folio/stripes-dep1/icons/otherthing.png deleted file mode 100644 index e69de29..0000000 diff --git a/test/webpack/node_modules/@folio/stripes-dep1/icons/otherthing.svg b/test/webpack/node_modules/@folio/stripes-dep1/icons/otherthing.svg deleted file mode 100644 index e69de29..0000000 diff --git a/test/webpack/node_modules/@folio/stripes-dep1/icons/thing.png b/test/webpack/node_modules/@folio/stripes-dep1/icons/thing.png deleted file mode 100644 index e69de29..0000000 diff --git a/test/webpack/node_modules/@folio/stripes-dep1/icons/thing.svg b/test/webpack/node_modules/@folio/stripes-dep1/icons/thing.svg deleted file mode 100644 index e69de29..0000000 diff --git a/test/webpack/node_modules/@folio/stripes-dep1/package.json b/test/webpack/node_modules/@folio/stripes-dep1/package.json deleted file mode 100644 index 0bc5dda..0000000 --- a/test/webpack/node_modules/@folio/stripes-dep1/package.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "@folio/stripes-dep1", - "version": "3.4.5", - "main": "src/index.js", - "stripes": { - "icons": [ - { - "name": "thing", - "alt": "Do thing", - "title": "Thingy" - }, - { - "name": "otherthing", - "alt": "Do other thing", - "title": "Other Thing" - } - ] - } -} diff --git a/test/webpack/node_modules/@notfolio/stripes-dep2/package.json b/test/webpack/node_modules/@notfolio/stripes-dep2/package.json deleted file mode 100644 index 8db0fd5..0000000 --- a/test/webpack/node_modules/@notfolio/stripes-dep2/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "@notfolio/stripes-dep2", - "version": "1.2.3", - "main": "src/index.js" -} diff --git a/webpack.config.base.js b/webpack.config.base.js index c889ff4..3f03465 100644 --- a/webpack.config.base.js +++ b/webpack.config.base.js @@ -15,7 +15,6 @@ const specificReact = generateStripesAlias('react'); module.exports = { entry: [ - '@folio/stripes-components/lib/global.css', '@folio/stripes-core/src/index', //path.join(__dirname, 'src', 'index'), ], diff --git a/webpack.config.cli.dev.js b/webpack.config.cli.dev.js index d279009..2eb0c25 100644 --- a/webpack.config.cli.dev.js +++ b/webpack.config.cli.dev.js @@ -3,31 +3,12 @@ const path = require('path'); const webpack = require('webpack'); -const postCssImport = require('postcss-import'); -const autoprefixer = require('autoprefixer'); -const postCssCustomProperties = require('postcss-custom-properties'); -const postCssCalc = require('postcss-calc'); -const postCssNesting = require('postcss-nesting'); -const postCssCustomMedia = require('postcss-custom-media'); -const postCssMediaMinMax = require('postcss-media-minmax'); -const postCssColorFunction = require('postcss-color-function'); -const { generateStripesAlias, tryResolve, getSharedStyles } = require('./webpack/module-paths'); + +const { tryResolve } = require('./webpack/module-paths'); const base = require('./webpack.config.base'); const cli = require('./webpack.config.cli'); - -const locateCssVariables = () => { - const variables = 'lib/variables.css'; - const localPath = path.join(path.resolve(), variables); - - // check if variables are present locally (in cases when stripes-components is - // being built directly) if not look for them via stripes aliases - return tryResolve(localPath) ? - localPath : - path.join(generateStripesAlias('@folio/stripes-components'), variables); -}; - const useBrowserMocha = () => { return tryResolve('mocha/mocha-es2018.js') ? 'mocha/mocha-es2018.js' : 'mocha'; }; @@ -62,45 +43,10 @@ devConfig.plugins = devConfig.plugins.concat([ devConfig.resolve.alias['react-dom'] = '@hot-loader/react-dom'; devConfig.resolve.alias.process = 'process/browser.js'; devConfig.resolve.alias['mocha'] = useBrowserMocha(); -devConfig.module.rules.push({ - test: /\.css$/, - use: [ - { - loader: 'style-loader' - }, - { - loader: 'css-loader', - options: { - modules: { - localIdentName: '[local]---[hash:base64:5]', - }, - sourceMap: true, - importLoaders: 1, - }, - }, - { - loader: 'postcss-loader', - options: { - postcssOptions: { - plugins: [ - postCssImport(), - autoprefixer(), - postCssCustomProperties({ - preserve: false, - importFrom: [locateCssVariables()] - }), - postCssCalc(), - postCssNesting(), - postCssCustomMedia(), - postCssMediaMinMax(), - postCssColorFunction(), - ], - }, - sourceMap: true, - }, - }, - ], -}); + +// add the css workflow, handling themes... + + // add 'Buffer' global required for tests/reporting tools. devConfig.plugins.push( diff --git a/webpack.config.css.js b/webpack.config.css.js new file mode 100644 index 0000000..febe8d4 --- /dev/null +++ b/webpack.config.css.js @@ -0,0 +1,102 @@ +const path = require('path'); +const postCssImport = require('postcss-import'); +const autoprefixer = require('autoprefixer'); +const postCssCustomProperties = require('postcss-custom-properties'); +const postCssCalc = require('postcss-calc'); +const postCssNesting = require('postcss-nesting'); +const postCssCustomMedia = require('postcss-custom-media'); +const postCssMediaMinMax = require('postcss-media-minmax'); +const postCssColorFunction = require('postcss-color-function'); +const postCssOmitImports = require('./webpack/postcss/postcss-omit-imports'); + +const { generateStripesAlias, tryResolve } = require('./webpack/module-paths'); + +const locateCssVariables = () => { + const variables = 'lib/variables.css'; + const localPath = path.join(path.resolve(), variables); + + // check if variables are present locally (in cases when stripes-components is + // being built directly) if not look for them via stripes aliases + return tryResolve(localPath) ? + localPath : + path.join(generateStripesAlias('@folio/stripes-components'), variables); +}; + +const locateTheme = (themePath) => { + return tryResolve(themePath) ? + themePath : path.join('..', themePath); +} + +const getCSSVariableSettings = (stripesConfig) => { + const settings = {}; + // preserve: false removes css variable entries, leaving only the baked CSS variables. + if (stripesConfig.legacyCSS) { + settings.preserve = false; + } + + // settings.importFrom = [ locateCssVariables() ]; + + // // imports a theme from stripes-config. + // if (stripesConfig.theme) { + // settings.importFrom.push(locateTheme(stripesConfig.theme)) + // } + + return settings; +} + + +module.exports = (config, context, stripesConfig) => { + let cssEntries = [ + locateCssVariables(), + '@folio/stripes-components/lib/global.css', + ] + + if (stripesConfig.theme) { + cssEntries = [...cssEntries, locateTheme(stripesConfig.theme)] + } + + config.entry = [ + ...cssEntries, + ...config.entry + ]; + + config.module.rules.push({ + test: /\.css$/, + use: [ + { + loader: 'style-loader' + }, + { + loader: 'css-loader', + options: { + modules: { + localIdentName: '[local]---[hash:base64:5]', + }, + sourceMap: true, + importLoaders: 1, + }, + }, + { + loader: 'postcss-loader', + options: { + postcssOptions: { + plugins: [ + autoprefixer(), + postCssCustomProperties( + getCSSVariableSettings(stripesConfig) + ), + postCssCalc(), + postCssNesting(), + postCssCustomMedia(), + postCssMediaMinMax(), + postCssColorFunction(), + ], + }, + sourceMap: true, + }, + }, + ], + }); + + return config; +} diff --git a/webpack/postcss/postcss-omit-imports/index.js b/webpack/postcss/postcss-omit-imports/index.js new file mode 100644 index 0000000..9f58b33 --- /dev/null +++ b/webpack/postcss/postcss-omit-imports/index.js @@ -0,0 +1,14 @@ +module.exports = (opts = { contains: /variables/ }) => { + return { + postcssPlugin: 'postcss-omit-imports', + AtRuleExit: { + import: atRule => { + if (opts.contains.test(atRule.params)) { + atRule.remove(); + } + } + } + } +}; + +module.exports.postcss = true; \ No newline at end of file diff --git a/webpack/postcss/postcss-omit-imports/omit.test.js b/webpack/postcss/postcss-omit-imports/omit.test.js new file mode 100644 index 0000000..846894f --- /dev/null +++ b/webpack/postcss/postcss-omit-imports/omit.test.js @@ -0,0 +1,133 @@ +const postcss = require('postcss'); +const plugin = require('./'); +const mocha = require('mocha'); +const chai = require('chai'); + +const { + describe, + it +} = mocha; + +const { expect } = chai; + +function run(input, output, opts) { + return postcss([plugin(opts)]).process(input, { from: undefined }).then(result => { + expect(result.css).to.equal(output); + }) + .catch(err => {}); +} + +describe('omit imports', () => { + it('removes the import statement as expected',() => { + run(ex, exOut); + }) +}); + +describe('leaves other imports in place', () => { + it('removes the import statement as expected',() => { + run(ex2, ex2Out); + }) +}); + + +const ex = ` +/** + * Shared form styles + */ + +@import "../variables.css"; +@import "some/other/file.css"; + +.inputGroup { + position: relative; +} + +/** + * Default input, textarea and select styling + */ +.formControl { + margin-bottom: var(--control-margin-bottom); + border: 1px solid var(--color-border-form); + color: var(--color-text); + background-color: var(--color-fill-form-element); + + &::-ms-clear { + display: none; + } +} +`; + +const exOut = ` +/** + * Shared form styles + */ + +@import "some/other/file.css"; + +.inputGroup { + position: relative; +} + +/** + * Default input, textarea and select styling + */ +.formControl { + margin-bottom: var(--control-margin-bottom); + border: 1px solid var(--color-border-form); + color: var(--color-text); + background-color: var(--color-fill-form-element); + + &::-ms-clear { + display: none; + } +} +`; + + +const ex2 = ` +@import '../variables.css'; +@import "some/other/file.css"; + +/** +* Default styling +*/ + +.button { + composes: interactionStyles from "../sharedStyles/interactionStyles.css"; + padding: 0 var(--gutter-static); + -webkit-appearance: none; + cursor: pointer; + border: transparent; + + &:visited { + color: inherit; + } + + &::before { + border-radius: 999px; + } +} +`; +const ex2Out =` +@import "some/other/file.css"; + +/** +* Default styling +*/ + +.button { + composes: interactionStyles from "../sharedStyles/interactionStyles.css"; + padding: 0 var(--gutter-static); + -webkit-appearance: none; + cursor: pointer; + border: transparent; + + &:visited { + color: inherit; + } + + &::before { + border-radius: 999px; + } +} +`; \ No newline at end of file diff --git a/webpack/serve.js b/webpack/serve.js index 4ce2986..4000374 100644 --- a/webpack/serve.js +++ b/webpack/serve.js @@ -18,14 +18,17 @@ module.exports = function serve(stripesConfig, options) { if (typeof stripesConfig.okapi !== 'object') throw new Error('Missing Okapi config'); if (typeof stripesConfig.okapi.url !== 'string') throw new Error('Missing Okapi URL'); if (stripesConfig.okapi.url.endsWith('/')) throw new Error('Trailing slash in Okapi URL will prevent Stripes from functioning'); + return new Promise((resolve) => { logger.log('starting serve...'); const app = express(); let config = require('../webpack.config.cli.dev'); // eslint-disable-line global-require let developmentConfig = require('../webpack.config.cli.dev.shared.styles'); + let cssConfig = require('../webpack.config.css'); if (process.env.NODE_ENV === 'development') { config = developmentConfig(config, {}); + config = cssConfig(config, {}, stripesConfig); } config.plugins.push(new StripesWebpackPlugin({ stripesConfig })); From 7e907c16ffcabd77a0f5f188a95cc1ec2f1c1b85 Mon Sep 17 00:00:00 2001 From: John Coburn Date: Thu, 3 Feb 2022 15:24:01 -0600 Subject: [PATCH 2/3] break CSS stack into separate function --- webpack.config.cli.dev.js | 4 ---- webpack.config.css.js | 12 ++++++++++-- webpack/serve.js | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/webpack.config.cli.dev.js b/webpack.config.cli.dev.js index 2eb0c25..9c2d556 100644 --- a/webpack.config.cli.dev.js +++ b/webpack.config.cli.dev.js @@ -44,10 +44,6 @@ devConfig.resolve.alias['react-dom'] = '@hot-loader/react-dom'; devConfig.resolve.alias.process = 'process/browser.js'; devConfig.resolve.alias['mocha'] = useBrowserMocha(); -// add the css workflow, handling themes... - - - // add 'Buffer' global required for tests/reporting tools. devConfig.plugins.push( new webpack.ProvidePlugin({ diff --git a/webpack.config.css.js b/webpack.config.css.js index febe8d4..0ee1145 100644 --- a/webpack.config.css.js +++ b/webpack.config.css.js @@ -27,7 +27,7 @@ const locateTheme = (themePath) => { themePath : path.join('..', themePath); } -const getCSSVariableSettings = (stripesConfig) => { +const getCSSVariableSettings = (stripesConfig, context) => { const settings = {}; // preserve: false removes css variable entries, leaving only the baked CSS variables. if (stripesConfig.legacyCSS) { @@ -45,7 +45,7 @@ const getCSSVariableSettings = (stripesConfig) => { } -module.exports = (config, context, stripesConfig) => { +module.exports = (config, stripesConfig, context) => { let cssEntries = [ locateCssVariables(), '@folio/stripes-components/lib/global.css', @@ -60,6 +60,13 @@ module.exports = (config, context, stripesConfig) => { ...config.entry ]; + // since entries will be stripped out by karma-webpack, we have to import CSS via postcss-import (inline them); + + const postCSSEntries = [] + if (context._.includes('karma')) { + postCSSEntries.push(postCssImport()); + } + config.module.rules.push({ test: /\.css$/, use: [ @@ -81,6 +88,7 @@ module.exports = (config, context, stripesConfig) => { options: { postcssOptions: { plugins: [ + ...postCSSEntries, autoprefixer(), postCssCustomProperties( getCSSVariableSettings(stripesConfig) diff --git a/webpack/serve.js b/webpack/serve.js index 4000374..2d77e71 100644 --- a/webpack/serve.js +++ b/webpack/serve.js @@ -28,7 +28,7 @@ module.exports = function serve(stripesConfig, options) { if (process.env.NODE_ENV === 'development') { config = developmentConfig(config, {}); - config = cssConfig(config, {}, stripesConfig); + config = cssConfig(config, {}, stripesConfig, options); } config.plugins.push(new StripesWebpackPlugin({ stripesConfig })); From 749a703630756f20f963df7cd9759367d8fc440c Mon Sep 17 00:00:00 2001 From: John Coburn Date: Mon, 7 Feb 2022 09:16:53 -0600 Subject: [PATCH 3/3] apply themes to production bundle --- webpack.config.cli.prod.js | 77 +++++++++---------- webpack.config.css.js | 63 +++++++++------ webpack/build.js | 3 + webpack/postcss/postcss-omit-imports/index.js | 17 ++-- .../postcss/postcss-omit-imports/omit.test.js | 26 ++++++- webpack/serve.js | 2 +- 6 files changed, 120 insertions(+), 68 deletions(-) diff --git a/webpack.config.cli.prod.js b/webpack.config.cli.prod.js index 2b9a804..62df02b 100644 --- a/webpack.config.cli.prod.js +++ b/webpack.config.cli.prod.js @@ -3,7 +3,7 @@ const path = require('path'); const webpack = require('webpack'); -const MiniCssExtractPlugin = require('mini-css-extract-plugin'); + const CssMinimizerPlugin = require("css-minimizer-webpack-plugin") const postCssImport = require('postcss-import'); @@ -28,7 +28,6 @@ const prodConfig = Object.assign({}, base, cli, { }); prodConfig.plugins = prodConfig.plugins.concat([ - new MiniCssExtractPlugin({ filename: 'style.[contenthash].css' }), new webpack.ProvidePlugin({ process: 'process/browser.js', }), @@ -49,43 +48,43 @@ prodConfig.optimization = { minimize: true, } -prodConfig.module.rules.push({ - test: /\.css$/, - use: [ - { - loader: MiniCssExtractPlugin.loader, - }, - { - loader: 'css-loader', - options: { - modules: { - localIdentName: '[local]---[hash:base64:5]', - }, - importLoaders: 1, - }, - }, - { - loader: 'postcss-loader', - options: { - postcssOptions: { - plugins: [ - postCssImport(), - autoprefixer(), - postCssCustomProperties({ - preserve: false, - importFrom: [path.join(generateStripesAlias('@folio/stripes-components'), 'lib/variables.css')] - }), - postCssCalc(), - postCssNesting(), - postCssCustomMedia(), - postCssMediaMinMax(), - postCssColorFunction(), - ], - }, - }, - }, - ], -}); +// prodConfig.module.rules.push({ +// test: /\.css$/, +// use: [ +// { +// loader: MiniCssExtractPlugin.loader, +// }, +// { +// loader: 'css-loader', +// options: { +// modules: { +// localIdentName: '[local]---[hash:base64:5]', +// }, +// importLoaders: 1, +// }, +// }, +// { +// loader: 'postcss-loader', +// options: { +// postcssOptions: { +// plugins: [ +// postCssImport(), +// autoprefixer(), +// postCssCustomProperties({ +// preserve: false, +// importFrom: [path.join(generateStripesAlias('@folio/stripes-components'), 'lib/variables.css')] +// }), +// postCssCalc(), +// postCssNesting(), +// postCssCustomMedia(), +// postCssMediaMinMax(), +// postCssColorFunction(), +// ], +// }, +// }, +// }, +// ], +// }); prodConfig.module.rules.push( { diff --git a/webpack.config.css.js b/webpack.config.css.js index 0ee1145..ed6f654 100644 --- a/webpack.config.css.js +++ b/webpack.config.css.js @@ -8,6 +8,7 @@ const postCssCustomMedia = require('postcss-custom-media'); const postCssMediaMinMax = require('postcss-media-minmax'); const postCssColorFunction = require('postcss-color-function'); const postCssOmitImports = require('./webpack/postcss/postcss-omit-imports'); +const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const { generateStripesAlias, tryResolve } = require('./webpack/module-paths'); @@ -27,59 +28,76 @@ const locateTheme = (themePath) => { themePath : path.join('..', themePath); } -const getCSSVariableSettings = (stripesConfig, context) => { +const getCSSVariableSettings = (stripesConfig) => { const settings = {}; // preserve: false removes css variable entries, leaving only the baked CSS variables. if (stripesConfig.legacyCSS) { settings.preserve = false; } - // settings.importFrom = [ locateCssVariables() ]; + settings.importFrom = []; - // // imports a theme from stripes-config. - // if (stripesConfig.theme) { - // settings.importFrom.push(locateTheme(stripesConfig.theme)) - // } + // imports a theme from stripes-config. + if (stripesConfig.theme) { + settings.importFrom.push(locateTheme(stripesConfig.theme)) + } return settings; } +module.exports = (wpconfig, stripesConfig, context) => { + let production = false; -module.exports = (config, stripesConfig, context) => { let cssEntries = [ locateCssVariables(), '@folio/stripes-components/lib/global.css', - ] - + ]; + let themeEntry = []; if (stripesConfig.theme) { - cssEntries = [...cssEntries, locateTheme(stripesConfig.theme)] + themeEntry = [locateTheme(stripesConfig.theme)]; } - config.entry = [ + wpconfig.entry = [ ...cssEntries, - ...config.entry + ...wpconfig.entry, + ...themeEntry ]; - // since entries will be stripped out by karma-webpack, we have to import CSS via postcss-import (inline them); + let postCSSEntries = [postCssOmitImports({ contains: /variables/ })]; - const postCSSEntries = [] +// since entries will be stripped out by karma-webpack, we have to import CSS via postcss-import (inline them); if (context._.includes('karma')) { - postCSSEntries.push(postCssImport()); + postCSSEntries = [postCssImport()]; } - config.module.rules.push({ + // default for development... style-loader. + let loaderEntries = [ + { + loader: 'style-loader' + }, + ]; + + // use CSS extraction for production instead of style-tag injection. + if (context._.includes('build')) { + production = true; + loaderEntries = [{ + loader: MiniCssExtractPlugin.loader, + }]; + + wpconfig.plugins.push(new MiniCssExtractPlugin({ filename: 'style.[contenthash].css' })); + } + + wpconfig.module.rules.push({ test: /\.css$/, use: [ - { - loader: 'style-loader' - }, + ...loaderEntries, { loader: 'css-loader', options: { modules: { localIdentName: '[local]---[hash:base64:5]', }, - sourceMap: true, + sourceMap: !production, importLoaders: 1, }, }, @@ -100,11 +118,12 @@ module.exports = (config, stripesConfig, context) => { postCssColorFunction(), ], }, - sourceMap: true, + sourceMap: !production, }, }, ], }); - return config; + // console.log(JSON.stringify(wpconfig, null, 2)); + return wpconfig; } diff --git a/webpack/build.js b/webpack/build.js index a175c64..d28ba12 100644 --- a/webpack/build.js +++ b/webpack/build.js @@ -11,6 +11,9 @@ module.exports = function build(stripesConfig, options) { return new Promise((resolve, reject) => { logger.log('starting build...'); let config = require('../webpack.config.cli.prod'); // eslint-disable-line global-require + let cssConfig = require('../webpack.config.css'); // eslint-disable-line global-require + + config = cssConfig(config, stripesConfig, options); if (!options.skipStripesBuild) { config.plugins.push(new StripesWebpackPlugin({ stripesConfig, createDll: options.createDll })); diff --git a/webpack/postcss/postcss-omit-imports/index.js b/webpack/postcss/postcss-omit-imports/index.js index 9f58b33..c844791 100644 --- a/webpack/postcss/postcss-omit-imports/index.js +++ b/webpack/postcss/postcss-omit-imports/index.js @@ -1,11 +1,18 @@ +/* omit-imports will remove imports that match the supplied 'contains' regex */ + module.exports = (opts = { contains: /variables/ }) => { return { postcssPlugin: 'postcss-omit-imports', - AtRuleExit: { - import: atRule => { - if (opts.contains.test(atRule.params)) { - atRule.remove(); - } + prepare (result) { + const removals = {} + return { + AtRuleExit: { + import: atRule => { + if (opts.contains.test(atRule.params)) { + atRule.remove(); + } + } + }, } } } diff --git a/webpack/postcss/postcss-omit-imports/omit.test.js b/webpack/postcss/postcss-omit-imports/omit.test.js index 846894f..2246ce1 100644 --- a/webpack/postcss/postcss-omit-imports/omit.test.js +++ b/webpack/postcss/postcss-omit-imports/omit.test.js @@ -29,6 +29,11 @@ describe('leaves other imports in place', () => { }) }); +describe('leaves other imports in place', () => { + it('removes the import statement as expected',() => { + run(ex3, ex3Out); + }) +}); const ex = ` /** @@ -130,4 +135,23 @@ const ex2Out =` border-radius: 999px; } } -`; \ No newline at end of file +`; + +const ex3 = ` +@import "../variables"; +@import "./styles/padding"; +@import "./styles/margin"; +@import "./styles/flexbox"; +@import "./styles/width"; +@import "./styles/text"; +@import "./styles/float"; +` + +const ex3Out = ` +@import "./styles/padding"; +@import "./styles/margin"; +@import "./styles/flexbox"; +@import "./styles/width"; +@import "./styles/text"; +@import "./styles/float"; +` \ No newline at end of file diff --git a/webpack/serve.js b/webpack/serve.js index 2d77e71..6713dd9 100644 --- a/webpack/serve.js +++ b/webpack/serve.js @@ -28,7 +28,7 @@ module.exports = function serve(stripesConfig, options) { if (process.env.NODE_ENV === 'development') { config = developmentConfig(config, {}); - config = cssConfig(config, {}, stripesConfig, options); + config = cssConfig(config, stripesConfig, options); } config.plugins.push(new StripesWebpackPlugin({ stripesConfig }));