diff --git a/README.md b/README.md index e62ee4a2..c053ea59 100644 --- a/README.md +++ b/README.md @@ -565,7 +565,6 @@ module.exports = { loader: 'css-loader', options: { modules: { - // All files for which /\.module\.\w+$/i.test(filename) return true auto: true, }, }, @@ -577,7 +576,7 @@ module.exports = { ###### `RegExp` -Enable css modules for files based on filename and satisfying `/youRegExp/.test(filename)` regex. +Enable css modules for files based on a filename and satisfying your regex. **webpack.config.js** @@ -590,8 +589,7 @@ module.exports = { loader: 'css-loader', options: { modules: { - // All files for which /youRegExp/i.test(filename) return true - auto: /youRegExp/i, + auto: /\.custom-module\.\w+$/i, }, }, }, @@ -609,9 +607,7 @@ Setup `mode` option. You can omit the value when you want `local` mode. ###### `String` -Possible values: - -`local`, `global`, `pure` +Possible values - `local`, `global`, and `pure`. **webpack.config.js** @@ -637,7 +633,7 @@ module.exports = { Allows set different values for the `mode` option based on a filename -Possible return values - `local`, `global` and `pure` +Possible return values - `local`, `global`, and `pure`. **webpack.config.js** @@ -650,9 +646,13 @@ module.exports = { loader: 'css-loader', options: { modules: { - // Callback must return "local", "global" or "pure" - mode: (filename) => { - if (/global.css$/i.test(filename)) { + // Callback must return "local", "global", or "pure" values + mode: (resourcePath) => { + if (/pure.css$/i.test(resourcePath)) { + return 'pure'; + } + + if (/global.css$/i.test(resourcePath)) { return 'global'; } @@ -1049,9 +1049,9 @@ For production builds it's recommended to extract the CSS from your bundle being - As an alternative, if seeking better development performance and css outputs that mimic production. [extract-css-chunks-webpack-plugin](https://github.com/faceyspacey/extract-css-chunks-webpack-plugin) offers a hot module reload friendly, extended version of mini-css-extract-plugin. HMR real CSS files in dev, works like mini-css in non-dev -### CSS modules and pure CSS +### Pure CSS, CSS modules and PostCSS -When you have pure CSS (without CSS modules) and CSS modules in project you can use this setup: +When you have pure CSS (without CSS modules), CSS modules and PostCSS in your project you can use this setup: **webpack.config.js** @@ -1059,23 +1059,34 @@ When you have pure CSS (without CSS modules) and CSS modules in project you can module.exports = { module: { rules: [ - { - // For pure CSS (without CSS modules) - test: /\.css$/i, - exclude: /\.module\.css$/i, - use: ['style-loader', 'css-loader'], - }, { // For CSS modules - test: /\.module\.css$/i, + // For pure CSS - /\.css$/i, + // For Sass/SCSS - /\.((c|sa|sc)ss)$/i, + // For Less - /\.((c|le)ss)$/i, + test: /\.((c|sa|sc)ss)$/i, use: [ 'style-loader', { loader: 'css-loader', options: { - modules: true, + // Run `postcss-loader` on each CSS `@import`, do not forget that `sass-loader` compile non CSS `@import`'s into a single file + // If you need run `sass-loader` and `postcss-loader` on each CSS `@import` please set it to `2` + importLoaders: 1, + // Automatically enable css modules for files satisfying `/\.module\.\w+$/i` RegExp. + modules: { auto: true }, }, }, + { + loader: 'postcss-loader', + options: { plugins: () => [postcssPresetEnv({ stage: 0 })] }, + }, + // Can be `less-loader` + // The `test` property should be `\.less/i` + { + test: /\.s[ac]ss$/i, + loader: 'sass-loader', + }, ], }, { diff --git a/test/__snapshots__/loader.test.js.snap b/test/__snapshots__/loader.test.js.snap index 9fefe6db..d5d503eb 100644 --- a/test/__snapshots__/loader.test.js.snap +++ b/test/__snapshots__/loader.test.js.snap @@ -578,6 +578,76 @@ a[href=\\"\\" i] { exports[`loader should work with empty options: warnings 1`] = `Array []`; +exports[`loader should work with the "modules.auto" option and the "importLoaders" option: errors 1`] = `Array []`; + +exports[`loader should work with the "modules.auto" option and the "importLoaders" option: result 1`] = ` +"/* Pure CSS */ +.imported-by-pure { + overflow-x: hidden; + overflow-y: auto; + overflow: hidden auto; +} +.pure { + color: red; +} + +/* PostCSS */ +.imported-by-postcss { + overflow-x: hidden; + overflow-y: auto; + overflow: hidden auto; +} +.postcss { + color: rgba(0, 0, 255, 0.9) +} + +.postcss:hover { + color: #639; + } + +/* SCSS */ +.imported-by-scss { + overflow-x: hidden; + overflow-y: auto; + overflow: hidden auto; +} +.scss { + font: 100% Helvetica, sans-serif; + color: #333; +} +/* CSS modules */ +.dA97I-anu7-0d9tFzAFON { + overflow-x: hidden; + overflow-y: auto; + overflow: hidden auto; + color: red; +} + +.global { + color: blue; +} + +/* CSS modules + SCSS */ +.imported-by-module-scss { + overflow-x: hidden; + overflow-y: auto; + overflow: hidden auto; +} +._2qRovssCxTKx1PYTv5qdNp { + color: #333; + overflow-x: hidden; + overflow-y: auto; + overflow: hidden auto; +} + +.global { + color: #333; +} +" +`; + +exports[`loader should work with the "modules.auto" option and the "importLoaders" option: warnings 1`] = `Array []`; + exports[`loader should work: errors 1`] = `Array []`; exports[`loader should work: module 1`] = ` diff --git a/test/fixtures/integration/css.module.css b/test/fixtures/integration/css.module.css new file mode 100644 index 00000000..0a789dbb --- /dev/null +++ b/test/fixtures/integration/css.module.css @@ -0,0 +1,8 @@ +.local { + overflow: hidden auto; + color: red; +} + +:global(.global) { + color: blue; +} diff --git a/test/fixtures/integration/imported-by-module-scss.css b/test/fixtures/integration/imported-by-module-scss.css new file mode 100644 index 00000000..7e2a3377 --- /dev/null +++ b/test/fixtures/integration/imported-by-module-scss.css @@ -0,0 +1,3 @@ +.imported-by-module-scss { + overflow: hidden auto; +} diff --git a/test/fixtures/integration/imported-by-postcss.css b/test/fixtures/integration/imported-by-postcss.css new file mode 100644 index 00000000..833e8c80 --- /dev/null +++ b/test/fixtures/integration/imported-by-postcss.css @@ -0,0 +1,3 @@ +.imported-by-postcss { + overflow: hidden auto; +} diff --git a/test/fixtures/integration/imported-by-pure.css b/test/fixtures/integration/imported-by-pure.css new file mode 100644 index 00000000..2f7c8d88 --- /dev/null +++ b/test/fixtures/integration/imported-by-pure.css @@ -0,0 +1,3 @@ +.imported-by-pure { + overflow: hidden auto; +} diff --git a/test/fixtures/integration/imported-by-scss.css b/test/fixtures/integration/imported-by-scss.css new file mode 100644 index 00000000..dbc20298 --- /dev/null +++ b/test/fixtures/integration/imported-by-scss.css @@ -0,0 +1,3 @@ +.imported-by-scss { + overflow: hidden auto; +} diff --git a/test/fixtures/integration/index.js b/test/fixtures/integration/index.js new file mode 100644 index 00000000..89cb15e2 --- /dev/null +++ b/test/fixtures/integration/index.js @@ -0,0 +1,9 @@ +import css1 from './pure.css'; +import css2 from './postcss.css'; +import css3 from './scss.scss'; +import css4 from './css.module.css'; +import css5 from './scss.module.scss'; + + __export__ = `/* Pure CSS */\n${css1}\n/* PostCSS */\n${css2}\n/* SCSS */\n${css3}\n/* CSS modules */\n${css4}\n/* CSS modules + SCSS */\n${css5}\n`; + +export default `/* Pure CSS */\n${css1}\n/* PostCSS */\n${css2}\n/* SCSS */\n${css3}\n/* CSS modules */\n${css4}\n/* CSS modules + SCSS */\n${css5}\n`; diff --git a/test/fixtures/integration/postcss.css b/test/fixtures/integration/postcss.css new file mode 100644 index 00000000..0c035a8c --- /dev/null +++ b/test/fixtures/integration/postcss.css @@ -0,0 +1,9 @@ +@import "./imported-by-postcss.css"; + +.postcss { + color: rgb(0 0 100% / 90%); + + &:hover { + color: rebeccapurple; + } +} diff --git a/test/fixtures/integration/pure.css b/test/fixtures/integration/pure.css new file mode 100644 index 00000000..c8f30ac1 --- /dev/null +++ b/test/fixtures/integration/pure.css @@ -0,0 +1,5 @@ +@import "./imported-by-pure.css"; + +.pure { + color: red; +} diff --git a/test/fixtures/integration/scss.module.scss b/test/fixtures/integration/scss.module.scss new file mode 100644 index 00000000..09835dce --- /dev/null +++ b/test/fixtures/integration/scss.module.scss @@ -0,0 +1,12 @@ +@import "./imported-by-module-scss.css"; + +$primary-color: #333; + +.local { + color: $primary-color; + overflow: hidden auto; +} + +:global(.global) { + color: $primary-color; +} diff --git a/test/fixtures/integration/scss.scss b/test/fixtures/integration/scss.scss new file mode 100644 index 00000000..c8a23444 --- /dev/null +++ b/test/fixtures/integration/scss.scss @@ -0,0 +1,9 @@ +@import "./imported-by-scss.css"; + +$font-stack: Helvetica, sans-serif; +$primary-color: #333; + +.scss { + font: 100% $font-stack; + color: $primary-color; +} diff --git a/test/loader.test.js b/test/loader.test.js index af438628..ccaee08c 100644 --- a/test/loader.test.js +++ b/test/loader.test.js @@ -2,6 +2,8 @@ import path from 'path'; import { version } from 'webpack'; +import postcssPresetEnv from 'postcss-preset-env'; + import { compile, getCompiler, @@ -352,4 +354,56 @@ describe('loader', () => { expect(getWarnings(stats)).toMatchSnapshot('warnings'); expect(getErrors(stats)).toMatchSnapshot('errors'); }); + + it('should work with the "modules.auto" option and the "importLoaders" option', async () => { + const compiler = getCompiler( + './integration/index.js', + {}, + { + module: { + rules: [ + { + test: /\.((c|sa|sc)ss)$/i, + rules: [ + { + loader: path.resolve(__dirname, '../src'), + options: { + // Run only `postcss-loader` on each `@import` + // If you need run `sass-loader` and `postcss-loader` please set it to `2` + importLoaders: 1, + // Automatically enable css modules for files satisfying `/\.module\.\w+$/i` RegExp. + modules: { auto: true }, + }, + }, + { + loader: 'postcss-loader', + options: { plugins: () => [postcssPresetEnv({ stage: 0 })] }, + }, + // Can be `less-loader` + // The `test` property should be `\.less/i` + { + test: /\.s[ac]ss$/i, + loader: 'sass-loader', + }, + ], + }, + { + test: /\.(png|jpe?g|gif|svg|eot|ttf|woff|woff2)$/i, + loader: 'url-loader', + options: { + limit: 8192, + }, + }, + ], + }, + } + ); + const stats = await compile(compiler); + + expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot( + 'result' + ); + expect(getWarnings(stats)).toMatchSnapshot('warnings'); + expect(getErrors(stats)).toMatchSnapshot('errors'); + }); });