From c558df903175e6938a3cdb3fe9aa7e6aa85755ee Mon Sep 17 00:00:00 2001 From: cap-Bernardito Date: Wed, 15 Jul 2020 19:19:12 +0300 Subject: [PATCH 1/7] feat: esModule export named --- README.md | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 57b406bb..b662a44c 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,7 @@ module.exports = { | **[`importLoaders`](#importloaders)** | `{Number}` | `0` | Enables/Disables or setups number of loaders applied before CSS loader | | **[`onlyLocals`](#onlylocals)** | `{Boolean}` | `false` | Export only locals | | **[`esModule`](#esmodule)** | `{Boolean}` | `false` | Use ES modules syntax | +| **[`namedExport`](#namedExport)** | `{Boolean}` | `false` | Use ES modules named export | ### `url` @@ -531,7 +532,6 @@ module.exports = { mode: 'local', exportGlobals: true, localIdentName: '[path][name]__[local]--[hash:base64:5]', - localsConvention: 'camelCase', context: path.resolve(__dirname, 'src'), hashPrefix: 'my-custom-hash', namedExport: true, @@ -1089,6 +1089,56 @@ module.exports = { }; ``` +### `namedExport` + +Type: `Boolean` +Default: `false` + +Enable/disable ES modules named export for css classes. +Names of exported classes are converted to camelCase. + +**styles.css** + +```css +.foo-baz { + color: red; +} +.bar { + color: blue; +} +``` + +**index.js** + +```js +import { fooBaz, bar } from './styles.css'; + +console.log(fooBaz, bar); +``` + +You can enable a ES module named export using: + +**webpack.config.js** + +```js +module.exports = { + module: { + rules: [ + { + test: /\.css$/i, + loader: 'css-loader', + options: { + esModule: true, + modules: { + namedExport: true, + }, + }, + }, + ], + }, +}; +``` + ## Examples ### Assets From 8d3f04977cd3457e38379b443a7cf5f179870c1c Mon Sep 17 00:00:00 2001 From: cap-Bernardito Date: Thu, 16 Jul 2020 13:51:58 +0300 Subject: [PATCH 2/7] feat: namedExport --- README.md | 52 +--------------------------------------------------- 1 file changed, 1 insertion(+), 51 deletions(-) diff --git a/README.md b/README.md index b662a44c..57b406bb 100644 --- a/README.md +++ b/README.md @@ -118,7 +118,6 @@ module.exports = { | **[`importLoaders`](#importloaders)** | `{Number}` | `0` | Enables/Disables or setups number of loaders applied before CSS loader | | **[`onlyLocals`](#onlylocals)** | `{Boolean}` | `false` | Export only locals | | **[`esModule`](#esmodule)** | `{Boolean}` | `false` | Use ES modules syntax | -| **[`namedExport`](#namedExport)** | `{Boolean}` | `false` | Use ES modules named export | ### `url` @@ -532,6 +531,7 @@ module.exports = { mode: 'local', exportGlobals: true, localIdentName: '[path][name]__[local]--[hash:base64:5]', + localsConvention: 'camelCase', context: path.resolve(__dirname, 'src'), hashPrefix: 'my-custom-hash', namedExport: true, @@ -1089,56 +1089,6 @@ module.exports = { }; ``` -### `namedExport` - -Type: `Boolean` -Default: `false` - -Enable/disable ES modules named export for css classes. -Names of exported classes are converted to camelCase. - -**styles.css** - -```css -.foo-baz { - color: red; -} -.bar { - color: blue; -} -``` - -**index.js** - -```js -import { fooBaz, bar } from './styles.css'; - -console.log(fooBaz, bar); -``` - -You can enable a ES module named export using: - -**webpack.config.js** - -```js -module.exports = { - module: { - rules: [ - { - test: /\.css$/i, - loader: 'css-loader', - options: { - esModule: true, - modules: { - namedExport: true, - }, - }, - }, - ], - }, -}; -``` - ## Examples ### Assets From 49b56906c5115ac7ef7fe1e953048c2cd60c45d8 Mon Sep 17 00:00:00 2001 From: cap-Bernardito Date: Thu, 16 Jul 2020 14:35:07 +0300 Subject: [PATCH 3/7] refactor: enable esModules by default --- package.json | 1 + test/__snapshots__/loader.test.js.snap | 140 +++++++++++++++++++++++++ test/helpers/index.js | 2 + test/helpers/runInJsDom.js | 44 ++++++++ test/loader.test.js | 138 ++++++++++++++++++++++++ 5 files changed, 325 insertions(+) create mode 100644 test/helpers/runInJsDom.js diff --git a/package.json b/package.json index c7035413..312847cc 100644 --- a/package.json +++ b/package.json @@ -76,6 +76,7 @@ "file-loader": "^6.0.0", "husky": "^4.2.5", "jest": "^26.1.0", + "jsdom": "^16.3.0", "lint-staged": "^10.2.11", "memfs": "^3.2.0", "mini-css-extract-plugin": "^0.9.0", diff --git a/test/__snapshots__/loader.test.js.snap b/test/__snapshots__/loader.test.js.snap index acc8a8fb..cfe5a918 100644 --- a/test/__snapshots__/loader.test.js.snap +++ b/test/__snapshots__/loader.test.js.snap @@ -381,6 +381,76 @@ exports[`loader should work with ModuleConcatenationPlugin: errors 1`] = `Array exports[`loader should work with ModuleConcatenationPlugin: warnings 1`] = `Array []`; +exports[`loader should work with commonjs-css-loader + commonjs-mini-css-extract-plugin: css 1`] = ` +".some-class { + color: red; +} + +" +`; + +exports[`loader should work with commonjs-css-loader + commonjs-mini-css-extract-plugin: errors 1`] = `Array []`; + +exports[`loader should work with commonjs-css-loader + commonjs-mini-css-extract-plugin: result 1`] = `Object {}`; + +exports[`loader should work with commonjs-css-loader + commonjs-mini-css-extract-plugin: warnings 1`] = `Array []`; + +exports[`loader should work with commonjs-css-loader + commonjs-style-loader: DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`loader should work with commonjs-css-loader + commonjs-style-loader: errors 1`] = `Array []`; + +exports[`loader should work with commonjs-css-loader + commonjs-style-loader: warnings 1`] = `Array []`; + +exports[`loader should work with commonjs-css-loader + esModule-mini-css-extract-plugin: css 1`] = ` +".some-class { + color: red; +} + +" +`; + +exports[`loader should work with commonjs-css-loader + esModule-mini-css-extract-plugin: errors 1`] = `Array []`; + +exports[`loader should work with commonjs-css-loader + esModule-mini-css-extract-plugin: result 1`] = `Object {}`; + +exports[`loader should work with commonjs-css-loader + esModule-mini-css-extract-plugin: warnings 1`] = `Array []`; + +exports[`loader should work with commonjs-css-loader + esModule-style-loader: DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`loader should work with commonjs-css-loader + esModule-style-loader: errors 1`] = `Array []`; + +exports[`loader should work with commonjs-css-loader + esModule-style-loader: warnings 1`] = `Array []`; + exports[`loader should work with empty css: errors 1`] = `Array []`; exports[`loader should work with empty css: module 1`] = ` @@ -579,6 +649,76 @@ a[href=\\"\\" i] { exports[`loader should work with empty options: warnings 1`] = `Array []`; +exports[`loader should work with esModule-css-loader + commonjs-mini-css-extract-plugin: css 1`] = ` +".some-class { + color: red; +} + +" +`; + +exports[`loader should work with esModule-css-loader + commonjs-mini-css-extract-plugin: errors 1`] = `Array []`; + +exports[`loader should work with esModule-css-loader + commonjs-mini-css-extract-plugin: result 1`] = `Object {}`; + +exports[`loader should work with esModule-css-loader + commonjs-mini-css-extract-plugin: warnings 1`] = `Array []`; + +exports[`loader should work with esModule-css-loader + commonjs-style-loader: DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`loader should work with esModule-css-loader + commonjs-style-loader: errors 1`] = `Array []`; + +exports[`loader should work with esModule-css-loader + commonjs-style-loader: warnings 1`] = `Array []`; + +exports[`loader should work with esModule-css-loader + esModule-mini-css-extract-plugin: css 1`] = ` +".some-class { + color: red; +} + +" +`; + +exports[`loader should work with esModule-css-loader + esModule-mini-css-extract-plugin: errors 1`] = `Array []`; + +exports[`loader should work with esModule-css-loader + esModule-mini-css-extract-plugin: result 1`] = `Object {}`; + +exports[`loader should work with esModule-css-loader + esModule-mini-css-extract-plugin: warnings 1`] = `Array []`; + +exports[`loader should work with esModule-css-loader + esModule-style-loader: DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`loader should work with esModule-css-loader + esModule-style-loader: errors 1`] = `Array []`; + +exports[`loader should work with esModule-css-loader + esModule-style-loader: 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`] = ` diff --git a/test/helpers/index.js b/test/helpers/index.js index 1dbb72f0..17a7ee48 100644 --- a/test/helpers/index.js +++ b/test/helpers/index.js @@ -8,6 +8,7 @@ import getWarnings from './getWarnings'; import normalizeErrors from './normalizeErrors'; import readAsset from './readAsset'; import readsAssets from './readAssets'; +import runInJsDom from './runInJsDom'; export { compile, @@ -20,4 +21,5 @@ export { normalizeErrors, readAsset, readsAssets, + runInJsDom, }; diff --git a/test/helpers/runInJsDom.js b/test/helpers/runInJsDom.js new file mode 100644 index 00000000..088751fb --- /dev/null +++ b/test/helpers/runInJsDom.js @@ -0,0 +1,44 @@ +import jsdom from 'jsdom'; + +import { readAsset } from './index'; + +function runInJsDom(assetName, compiler, stats, testFn) { + const bundle = readAsset(assetName, compiler, stats); + const virtualConsole = new jsdom.VirtualConsole(); + + virtualConsole.sendTo(console); + + try { + const dom = new jsdom.JSDOM( + ` + + + style-loader test + + + +

Body

+
+ + + +`, + { + resources: 'usable', + runScripts: 'dangerously', + virtualConsole, + } + ); + + dom.window.eval(bundle); + + testFn(dom); + + // free memory associated with the window + dom.window.close(); + } catch (e) { + throw e; + } +} + +export default runInJsDom; diff --git a/test/loader.test.js b/test/loader.test.js index b4d1a1df..f2265a38 100644 --- a/test/loader.test.js +++ b/test/loader.test.js @@ -11,8 +11,12 @@ import { getExecutedCode, getModuleSource, getWarnings, + readAsset, + runInJsDom, } from './helpers/index'; +const MiniCssExtractPlugin = require('mini-css-extract-plugin'); + jest.setTimeout(10000); describe('loader', () => { @@ -411,4 +415,138 @@ describe('loader', () => { expect(getWarnings(stats)).toMatchSnapshot('warnings'); expect(getErrors(stats)).toMatchSnapshot('errors'); }); + + const miniCssExtractPluginTests = [ + { + localLoaderMode: 'commonjs', + extractLoaderMode: 'commonjs', + }, + { + localLoaderMode: 'esModule', + extractLoaderMode: 'esModule', + }, + { + localLoaderMode: 'commonjs', + extractLoaderMode: 'esModule', + }, + { + localLoaderMode: 'esModule', + extractLoaderMode: 'commonjs', + }, + ]; + + for (const test of miniCssExtractPluginTests) { + it(`should work with ${test.localLoaderMode}-css-loader + ${test.extractLoaderMode}-mini-css-extract-plugin`, async () => { + const compiler = getCompiler( + './simple.js', + { + esModule: test.localLoaderMode === 'esModule', + }, + { + module: { + rules: [ + { + test: /\.css$/i, + use: [ + { + loader: MiniCssExtractPlugin.loader, + options: { + esModule: test.extractLoaderMode === 'esModule', + }, + }, + { + loader: path.resolve(__dirname, '../src'), + options: {}, + }, + ], + }, + { + test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2)$/i, + loader: 'file-loader', + options: { name: '[name].[ext]' }, + }, + ], + }, + plugins: [ + new MiniCssExtractPlugin({ + filename: '[name].css', + chunkFilename: '[id].css', + }), + ], + } + ); + const stats = await compile(compiler); + + expect(readAsset('main.css', compiler, stats)).toMatchSnapshot('css'); + expect( + getExecutedCode('main.bundle.js', compiler, stats) + ).toMatchSnapshot('result'); + expect(getWarnings(stats)).toMatchSnapshot('warnings'); + expect(getErrors(stats)).toMatchSnapshot('errors'); + }); + } + + const styleLoaderTests = [ + { + localLoaderMode: 'commonjs', + extractLoaderMode: 'commonjs', + }, + { + localLoaderMode: 'esModule', + extractLoaderMode: 'esModule', + }, + { + localLoaderMode: 'commonjs', + extractLoaderMode: 'esModule', + }, + { + localLoaderMode: 'esModule', + extractLoaderMode: 'commonjs', + }, + ]; + + for (const test of styleLoaderTests) { + it(`should work with ${test.localLoaderMode}-css-loader + ${test.extractLoaderMode}-style-loader`, async () => { + const compiler = getCompiler( + './simple-style.js', + { + esModule: test.localLoaderMode === 'esModule', + }, + { + module: { + rules: [ + { + test: /\.css$/i, + use: [ + { + loader: 'style-loader', + options: { + esModule: test.extractLoaderMode === 'esModule', + }, + }, + { + loader: path.resolve(__dirname, '../src'), + options: {}, + }, + ], + }, + { + test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2)$/i, + loader: 'file-loader', + options: { name: '[name].[ext]' }, + }, + ], + }, + } + ); + const stats = await compile(compiler); + + runInJsDom('main.bundle.js', compiler, stats, (dom) => { + expect(dom.serialize()).toMatchSnapshot('DOM'); + }); + + expect(getWarnings(stats)).toMatchSnapshot('warnings'); + expect(getErrors(stats)).toMatchSnapshot('errors'); + }); + } }); From a897a3d3e70374c90e1ae4e39c18a5ddc48d8d87 Mon Sep 17 00:00:00 2001 From: cap-Bernardito Date: Thu, 16 Jul 2020 15:52:54 +0300 Subject: [PATCH 4/7] refactor: enable esModules by default --- test/__snapshots__/url-option.test.js.snap | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/__snapshots__/url-option.test.js.snap b/test/__snapshots__/url-option.test.js.snap index 41a449f9..cbfea734 100644 --- a/test/__snapshots__/url-option.test.js.snap +++ b/test/__snapshots__/url-option.test.js.snap @@ -414,8 +414,8 @@ a { background: url(\\"/webpack/public/path/img'() img.png\\"); background-image: image-set( - - + + url(\\"/webpack/public/path/img'''img.png\\") 2x, url(\\"/webpack/public/path/img'img.png\\") 3x, url(\\"/webpack/public/path/img(img.png\\") 4x, @@ -1782,8 +1782,8 @@ a { background: url(\\"/webpack/public/path/img'() img.png\\"); background-image: image-set( - - + + url(\\"/webpack/public/path/img'''img.png\\") 2x, url(\\"/webpack/public/path/img'img.png\\") 3x, url(\\"/webpack/public/path/img(img.png\\") 4x, From 4975d2c40aa98387accd0e8fe0cfca4b28b4d1ef Mon Sep 17 00:00:00 2001 From: cap-Bernardito Date: Thu, 16 Jul 2020 18:36:34 +0300 Subject: [PATCH 5/7] refactor: rebase --- test/__snapshots__/url-option.test.js.snap | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/__snapshots__/url-option.test.js.snap b/test/__snapshots__/url-option.test.js.snap index cbfea734..41a449f9 100644 --- a/test/__snapshots__/url-option.test.js.snap +++ b/test/__snapshots__/url-option.test.js.snap @@ -414,8 +414,8 @@ a { background: url(\\"/webpack/public/path/img'() img.png\\"); background-image: image-set( - - + + url(\\"/webpack/public/path/img'''img.png\\") 2x, url(\\"/webpack/public/path/img'img.png\\") 3x, url(\\"/webpack/public/path/img(img.png\\") 4x, @@ -1782,8 +1782,8 @@ a { background: url(\\"/webpack/public/path/img'() img.png\\"); background-image: image-set( - - + + url(\\"/webpack/public/path/img'''img.png\\") 2x, url(\\"/webpack/public/path/img'img.png\\") 3x, url(\\"/webpack/public/path/img(img.png\\") 4x, From 0378f388a425a2b6171e91f6dd8d75da6a7d3fb7 Mon Sep 17 00:00:00 2001 From: cap-Bernardito Date: Thu, 16 Jul 2020 20:52:49 +0300 Subject: [PATCH 6/7] refactor: esModule enable by default --- package.json | 1 - test/__snapshots__/loader.test.js.snap | 140 ------------------------- test/helpers/index.js | 2 - test/helpers/runInJsDom.js | 44 -------- test/loader.test.js | 138 ------------------------ 5 files changed, 325 deletions(-) delete mode 100644 test/helpers/runInJsDom.js diff --git a/package.json b/package.json index 312847cc..c7035413 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,6 @@ "file-loader": "^6.0.0", "husky": "^4.2.5", "jest": "^26.1.0", - "jsdom": "^16.3.0", "lint-staged": "^10.2.11", "memfs": "^3.2.0", "mini-css-extract-plugin": "^0.9.0", diff --git a/test/__snapshots__/loader.test.js.snap b/test/__snapshots__/loader.test.js.snap index cfe5a918..acc8a8fb 100644 --- a/test/__snapshots__/loader.test.js.snap +++ b/test/__snapshots__/loader.test.js.snap @@ -381,76 +381,6 @@ exports[`loader should work with ModuleConcatenationPlugin: errors 1`] = `Array exports[`loader should work with ModuleConcatenationPlugin: warnings 1`] = `Array []`; -exports[`loader should work with commonjs-css-loader + commonjs-mini-css-extract-plugin: css 1`] = ` -".some-class { - color: red; -} - -" -`; - -exports[`loader should work with commonjs-css-loader + commonjs-mini-css-extract-plugin: errors 1`] = `Array []`; - -exports[`loader should work with commonjs-css-loader + commonjs-mini-css-extract-plugin: result 1`] = `Object {}`; - -exports[`loader should work with commonjs-css-loader + commonjs-mini-css-extract-plugin: warnings 1`] = `Array []`; - -exports[`loader should work with commonjs-css-loader + commonjs-style-loader: DOM 1`] = ` -" - style-loader test - - - -

Body

-
- - - -" -`; - -exports[`loader should work with commonjs-css-loader + commonjs-style-loader: errors 1`] = `Array []`; - -exports[`loader should work with commonjs-css-loader + commonjs-style-loader: warnings 1`] = `Array []`; - -exports[`loader should work with commonjs-css-loader + esModule-mini-css-extract-plugin: css 1`] = ` -".some-class { - color: red; -} - -" -`; - -exports[`loader should work with commonjs-css-loader + esModule-mini-css-extract-plugin: errors 1`] = `Array []`; - -exports[`loader should work with commonjs-css-loader + esModule-mini-css-extract-plugin: result 1`] = `Object {}`; - -exports[`loader should work with commonjs-css-loader + esModule-mini-css-extract-plugin: warnings 1`] = `Array []`; - -exports[`loader should work with commonjs-css-loader + esModule-style-loader: DOM 1`] = ` -" - style-loader test - - - -

Body

-
- - - -" -`; - -exports[`loader should work with commonjs-css-loader + esModule-style-loader: errors 1`] = `Array []`; - -exports[`loader should work with commonjs-css-loader + esModule-style-loader: warnings 1`] = `Array []`; - exports[`loader should work with empty css: errors 1`] = `Array []`; exports[`loader should work with empty css: module 1`] = ` @@ -649,76 +579,6 @@ a[href=\\"\\" i] { exports[`loader should work with empty options: warnings 1`] = `Array []`; -exports[`loader should work with esModule-css-loader + commonjs-mini-css-extract-plugin: css 1`] = ` -".some-class { - color: red; -} - -" -`; - -exports[`loader should work with esModule-css-loader + commonjs-mini-css-extract-plugin: errors 1`] = `Array []`; - -exports[`loader should work with esModule-css-loader + commonjs-mini-css-extract-plugin: result 1`] = `Object {}`; - -exports[`loader should work with esModule-css-loader + commonjs-mini-css-extract-plugin: warnings 1`] = `Array []`; - -exports[`loader should work with esModule-css-loader + commonjs-style-loader: DOM 1`] = ` -" - style-loader test - - - -

Body

-
- - - -" -`; - -exports[`loader should work with esModule-css-loader + commonjs-style-loader: errors 1`] = `Array []`; - -exports[`loader should work with esModule-css-loader + commonjs-style-loader: warnings 1`] = `Array []`; - -exports[`loader should work with esModule-css-loader + esModule-mini-css-extract-plugin: css 1`] = ` -".some-class { - color: red; -} - -" -`; - -exports[`loader should work with esModule-css-loader + esModule-mini-css-extract-plugin: errors 1`] = `Array []`; - -exports[`loader should work with esModule-css-loader + esModule-mini-css-extract-plugin: result 1`] = `Object {}`; - -exports[`loader should work with esModule-css-loader + esModule-mini-css-extract-plugin: warnings 1`] = `Array []`; - -exports[`loader should work with esModule-css-loader + esModule-style-loader: DOM 1`] = ` -" - style-loader test - - - -

Body

-
- - - -" -`; - -exports[`loader should work with esModule-css-loader + esModule-style-loader: errors 1`] = `Array []`; - -exports[`loader should work with esModule-css-loader + esModule-style-loader: 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`] = ` diff --git a/test/helpers/index.js b/test/helpers/index.js index 17a7ee48..1dbb72f0 100644 --- a/test/helpers/index.js +++ b/test/helpers/index.js @@ -8,7 +8,6 @@ import getWarnings from './getWarnings'; import normalizeErrors from './normalizeErrors'; import readAsset from './readAsset'; import readsAssets from './readAssets'; -import runInJsDom from './runInJsDom'; export { compile, @@ -21,5 +20,4 @@ export { normalizeErrors, readAsset, readsAssets, - runInJsDom, }; diff --git a/test/helpers/runInJsDom.js b/test/helpers/runInJsDom.js deleted file mode 100644 index 088751fb..00000000 --- a/test/helpers/runInJsDom.js +++ /dev/null @@ -1,44 +0,0 @@ -import jsdom from 'jsdom'; - -import { readAsset } from './index'; - -function runInJsDom(assetName, compiler, stats, testFn) { - const bundle = readAsset(assetName, compiler, stats); - const virtualConsole = new jsdom.VirtualConsole(); - - virtualConsole.sendTo(console); - - try { - const dom = new jsdom.JSDOM( - ` - - - style-loader test - - - -

Body

-
- - - -`, - { - resources: 'usable', - runScripts: 'dangerously', - virtualConsole, - } - ); - - dom.window.eval(bundle); - - testFn(dom); - - // free memory associated with the window - dom.window.close(); - } catch (e) { - throw e; - } -} - -export default runInJsDom; diff --git a/test/loader.test.js b/test/loader.test.js index f2265a38..b4d1a1df 100644 --- a/test/loader.test.js +++ b/test/loader.test.js @@ -11,12 +11,8 @@ import { getExecutedCode, getModuleSource, getWarnings, - readAsset, - runInJsDom, } from './helpers/index'; -const MiniCssExtractPlugin = require('mini-css-extract-plugin'); - jest.setTimeout(10000); describe('loader', () => { @@ -415,138 +411,4 @@ describe('loader', () => { expect(getWarnings(stats)).toMatchSnapshot('warnings'); expect(getErrors(stats)).toMatchSnapshot('errors'); }); - - const miniCssExtractPluginTests = [ - { - localLoaderMode: 'commonjs', - extractLoaderMode: 'commonjs', - }, - { - localLoaderMode: 'esModule', - extractLoaderMode: 'esModule', - }, - { - localLoaderMode: 'commonjs', - extractLoaderMode: 'esModule', - }, - { - localLoaderMode: 'esModule', - extractLoaderMode: 'commonjs', - }, - ]; - - for (const test of miniCssExtractPluginTests) { - it(`should work with ${test.localLoaderMode}-css-loader + ${test.extractLoaderMode}-mini-css-extract-plugin`, async () => { - const compiler = getCompiler( - './simple.js', - { - esModule: test.localLoaderMode === 'esModule', - }, - { - module: { - rules: [ - { - test: /\.css$/i, - use: [ - { - loader: MiniCssExtractPlugin.loader, - options: { - esModule: test.extractLoaderMode === 'esModule', - }, - }, - { - loader: path.resolve(__dirname, '../src'), - options: {}, - }, - ], - }, - { - test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2)$/i, - loader: 'file-loader', - options: { name: '[name].[ext]' }, - }, - ], - }, - plugins: [ - new MiniCssExtractPlugin({ - filename: '[name].css', - chunkFilename: '[id].css', - }), - ], - } - ); - const stats = await compile(compiler); - - expect(readAsset('main.css', compiler, stats)).toMatchSnapshot('css'); - expect( - getExecutedCode('main.bundle.js', compiler, stats) - ).toMatchSnapshot('result'); - expect(getWarnings(stats)).toMatchSnapshot('warnings'); - expect(getErrors(stats)).toMatchSnapshot('errors'); - }); - } - - const styleLoaderTests = [ - { - localLoaderMode: 'commonjs', - extractLoaderMode: 'commonjs', - }, - { - localLoaderMode: 'esModule', - extractLoaderMode: 'esModule', - }, - { - localLoaderMode: 'commonjs', - extractLoaderMode: 'esModule', - }, - { - localLoaderMode: 'esModule', - extractLoaderMode: 'commonjs', - }, - ]; - - for (const test of styleLoaderTests) { - it(`should work with ${test.localLoaderMode}-css-loader + ${test.extractLoaderMode}-style-loader`, async () => { - const compiler = getCompiler( - './simple-style.js', - { - esModule: test.localLoaderMode === 'esModule', - }, - { - module: { - rules: [ - { - test: /\.css$/i, - use: [ - { - loader: 'style-loader', - options: { - esModule: test.extractLoaderMode === 'esModule', - }, - }, - { - loader: path.resolve(__dirname, '../src'), - options: {}, - }, - ], - }, - { - test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2)$/i, - loader: 'file-loader', - options: { name: '[name].[ext]' }, - }, - ], - }, - } - ); - const stats = await compile(compiler); - - runInJsDom('main.bundle.js', compiler, stats, (dom) => { - expect(dom.serialize()).toMatchSnapshot('DOM'); - }); - - expect(getWarnings(stats)).toMatchSnapshot('warnings'); - expect(getErrors(stats)).toMatchSnapshot('errors'); - }); - } }); From 20da9f9e5ddf09d1bdadf50a8914cdef27555f33 Mon Sep 17 00:00:00 2001 From: cap-Bernardito Date: Fri, 17 Jul 2020 15:58:57 +0300 Subject: [PATCH 7/7] refactor: code --- README.md | 6 +++++ src/index.js | 22 ++++++++++++++++--- .../esModule-option.test.js.snap | 14 ++++++++++-- test/esModule-option.test.js | 14 ++++++++++++ 4 files changed, 51 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 57b406bb..b4fc46eb 100644 --- a/README.md +++ b/README.md @@ -766,6 +766,9 @@ Style of exported classnames. By default, the exported JSON keys mirror the class names (i.e `asIs` value). +When `namedExport` is enabled, the `localsConvention` option is ignored. +Do not use these options together. + | Name | Type | Description | | :-------------------: | :--------: | :----------------------------------------------------------------------------------------------- | | **`'asIs'`** | `{String}` | Class names will be exported as is. | @@ -924,6 +927,9 @@ Default: `false` Enable/disable ES modules named export for css classes. Names of exported classes are converted to camelCase. +When `namedExport` is enabled, the `localsConvention` option is ignored. +Do not use these options together. + > i It is not allowed to use JavaScript reserved words in css class names **styles.css** diff --git a/src/index.js b/src/index.js index 37d489c7..76791d1a 100644 --- a/src/index.js +++ b/src/index.js @@ -42,6 +42,8 @@ export default function loader(content, map, meta) { const urlHandler = (url) => stringifyRequest(this, preRequester(options.importLoaders) + url); + const callback = this.async(); + const esModule = typeof options.esModule !== 'undefined' ? options.esModule : true; @@ -51,11 +53,27 @@ export default function loader(content, map, meta) { modulesOptions = getModulesOptions(options, this); if (modulesOptions.namedExport === true && esModule === false) { - this.emitError( + callback( new Error( '`Options.module.namedExport` cannot be used without `options.esModule`' ) ); + + return; + } + + if ( + modulesOptions.namedExport === true && + modulesOptions.localsConvention !== 'asIs' && + modulesOptions.localsConvention !== 'camelCaseOnly' + ) { + callback( + new Error( + 'When `namedExport` is enabled class names are always converted to camelCase. Remove the `localsConvention` option from the webpack.config or set it to `asIs` / `camelCaseOnly`' + ) + ); + + return; } plugins.push(...getModulesPlugins(modulesOptions, this)); @@ -128,8 +146,6 @@ export default function loader(content, map, meta) { } } - const callback = this.async(); - postcss(plugins) .process(content, { from: this.resourcePath, diff --git a/test/__snapshots__/esModule-option.test.js.snap b/test/__snapshots__/esModule-option.test.js.snap index d2b974dc..83babb08 100644 --- a/test/__snapshots__/esModule-option.test.js.snap +++ b/test/__snapshots__/esModule-option.test.js.snap @@ -11,11 +11,21 @@ exports[`"esModule" option should emit error when class has unsupported name: wa exports[`"esModule" option should emit error when namedExport true && esModule false: errors 1`] = ` Array [ - "ModuleError: Module Error (from \`replaced original path\`): -\`Options.module.namedExport\` cannot be used without \`options.esModule\`", + "ModuleBuildError: Module build failed (from \`replaced original path\`): +Error: \`Options.module.namedExport\` cannot be used without \`options.esModule\` + at Object.loader (/src/index.js:57:9)", ] `; +exports[`"esModule" option should emit error when namedExport true && localsConvention invalid: errors 1`] = ` +Array [ + "ModuleBuildError: Module build failed (from \`replaced original path\`): +Error: When \`namedExport\` is enabled class names are always converted to camelCase. Remove the \`localsConvention\` option from the webpack.config or set it to \`asIs\` / \`camelCaseOnly\`", +] +`; + +exports[`"esModule" option should emit error when namedExport true && localsConvention invalid: warnings 1`] = `Array []`; + exports[`"esModule" option should work js template with "namedExport" option: errors 1`] = `Array []`; exports[`"esModule" option should work js template with "namedExport" option: module 1`] = ` diff --git a/test/esModule-option.test.js b/test/esModule-option.test.js index 592fcab1..a5b07d14 100644 --- a/test/esModule-option.test.js +++ b/test/esModule-option.test.js @@ -321,4 +321,18 @@ describe('"esModule" option', () => { expect(getErrors(stats)).toMatchSnapshot('errors'); }); + + it('should emit error when namedExport true && localsConvention invalid', async () => { + const compiler = getCompiler('./es-module/named/broken/index.js', { + esModule: true, + modules: { + namedExport: true, + localsConvention: 'dashes', + }, + }); + const stats = await compile(compiler); + + expect(getWarnings(stats)).toMatchSnapshot('warnings'); + expect(getErrors(stats, true)).toMatchSnapshot('errors'); + }); });