diff --git a/README.md b/README.md index 6ba17915..aeff8cea 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,7 @@ module.exports = { | **`attributes`** | `{Object}` | `{}` | Adds custom attributes to tag | | **`insert`** | `{String\|Function}` | `head` | Inserts tag at the given position into the DOM | | **`base`** | `{Number}` | `true` | Sets module ID base (DLLPlugin) | +| **`esModule`** | `{Boolean}` | `false` | Use ES modules syntax | ### `injectType` @@ -548,6 +549,34 @@ module.exports = { }; ``` +### `esModule` + +Type: `Boolean` +Default: `false` + +By default, `style-loader` generates JS modules that use the CommonJS modules syntax. +There are some cases in which using ES modules is beneficial, like in the case of [module concatenation](https://webpack.js.org/plugins/module-concatenation-plugin/) and [tree shaking](https://webpack.js.org/guides/tree-shaking/). + +You can enable a ES module syntax using: + +**webpack.config.js** + +```js +module.exports = { + module: { + rules: [ + { + test: /\.css$/i, + loader: 'css-loader', + options: { + esModule: true, + }, + }, + ], + }, +}; +``` + ## Examples ### Source maps diff --git a/src/index.js b/src/index.js index 8d9c2f4d..2328922c 100644 --- a/src/index.js +++ b/src/index.js @@ -21,8 +21,11 @@ loaderApi.pitch = function loader(request) { : typeof options.insert === 'string' ? JSON.stringify(options.insert) : options.insert.toString(); - const injectType = options.injectType || 'styleTag'; + const esModule = + typeof options.esModule !== 'undefined' ? options.esModule : false; + + delete options.esModule; switch (injectType) { case 'linkTag': { @@ -32,13 +35,18 @@ if (module.hot) { module.hot.accept( ${loaderUtils.stringifyRequest(this, `!!${request}`)}, function() { - var newContent = require(${loaderUtils.stringifyRequest( - this, - `!!${request}` - )}); - newContent = newContent.__esModule ? newContent.default : newContent; - - update(newContent); + ${ + esModule + ? `update(content);` + : `var newContent = require(${loaderUtils.stringifyRequest( + this, + `!!${request}` + )}); + + newContent = newContent.__esModule ? newContent.default : newContent; + + update(newContent);` + } } ); @@ -48,18 +56,34 @@ if (module.hot) { }` : ''; - return `var options = ${JSON.stringify(options)}; + return `${ + esModule + ? `import api from ${loaderUtils.stringifyRequest( + this, + `!${path.join(__dirname, 'runtime/injectStylesIntoLinkTag.js')}` + )}; + import content from ${loaderUtils.stringifyRequest( + this, + `!!${request}` + )};` + : `var api = require(${loaderUtils.stringifyRequest( + this, + `!${path.join(__dirname, 'runtime/injectStylesIntoLinkTag.js')}` + )}); + var content = require(${loaderUtils.stringifyRequest( + this, + `!!${request}` + )}); + + content = content.__esModule ? content.default : content;` + } -options.insert = ${insert}; +var options = ${JSON.stringify(options)}; -var content = require(${loaderUtils.stringifyRequest(this, `!!${request}`)}); -content = content.__esModule ? content.default : content; +options.insert = ${insert}; -var api = require(${loaderUtils.stringifyRequest( - this, - `!${path.join(__dirname, 'runtime/injectStylesIntoLinkTag.js')}` - )}); var update = api(content, options); + ${hmrCode}`; } @@ -71,9 +95,9 @@ ${hmrCode}`; ? ` if (module.hot) { var lastRefs = module.hot.data && module.hot.data.refs || 0; - + if (lastRefs) { - exports.use(); + exported.use(); if (!content.locals) { refs = lastRefs; @@ -94,42 +118,62 @@ if (module.hot) { }` : ''; - return `var refs = 0; -var dispose; -var content = require(${loaderUtils.stringifyRequest(this, `!!${request}`)}); -content = content.__esModule ? content.default : content; + return `${ + esModule + ? `import api from ${loaderUtils.stringifyRequest( + this, + `!${path.join(__dirname, 'runtime/injectStylesIntoStyleTag.js')}` + )}; + import content from ${loaderUtils.stringifyRequest( + this, + `!!${request}` + )};` + : `var api = require(${loaderUtils.stringifyRequest( + this, + `!${path.join(__dirname, 'runtime/injectStylesIntoStyleTag.js')}` + )}); + var content = require(${loaderUtils.stringifyRequest( + this, + `!!${request}` + )}); + + content = content.__esModule ? content.default : content; + + if (typeof content === 'string') { + content = [[module.id, content, '']]; + }` + } +var refs = 0; +var dispose; var options = ${JSON.stringify(options)}; options.insert = ${insert}; options.singleton = ${isSingleton}; -if (typeof content === 'string') { - content = [[module.id, content, '']]; -} +var exported = {}; if (content.locals) { - exports.locals = content.locals; + exported.locals = content.locals; } -exports.use = function() { +exported.use = function() { if (!(refs++)) { - var api = require(${loaderUtils.stringifyRequest( - this, - `!${path.join(__dirname, 'runtime/injectStylesIntoStyleTag.js')}` - )}); dispose = api(content, options); } - return exports; + return exported; }; -exports.unuse = function() { +exported.unuse = function() { if (refs > 0 && !--refs) { dispose(); dispose = null; } }; + +${esModule ? 'export default' : 'module.exports ='} exported; + ${hmrCode} `; } @@ -146,17 +190,22 @@ if (module.hot) { module.hot.accept( ${loaderUtils.stringifyRequest(this, `!!${request}`)}, function () { - var newContent = require(${loaderUtils.stringifyRequest( - this, - `!!${request}` - )}); - newContent = newContent.__esModule ? newContent.default : newContent; - - if (typeof newContent === 'string') { - newContent = [[module.id, newContent, '']]; + ${ + esModule + ? `update(content);` + : `var newContent = require(${loaderUtils.stringifyRequest( + this, + `!!${request}` + )}); + + newContent = newContent.__esModule ? newContent.default : newContent; + + if (typeof newContent === 'string') { + newContent = [[module.id, newContent, '']]; + } + + update(newContent);` } - - update(newContent); } ) } @@ -167,30 +216,44 @@ if (module.hot) { }` : ''; - return `var content = require(${loaderUtils.stringifyRequest( - this, - `!!${request}` - )}); -content = content.__esModule ? content.default : content; - -if (typeof content === 'string') { - content = [[module.id, content, '']]; -} + return `${ + esModule + ? `import api from ${loaderUtils.stringifyRequest( + this, + `!${path.join(__dirname, 'runtime/injectStylesIntoStyleTag.js')}` + )}; + import content from ${loaderUtils.stringifyRequest( + this, + `!!${request}` + )}; + var clonedContent = content;` + : `var api = require(${loaderUtils.stringifyRequest( + this, + `!${path.join(__dirname, 'runtime/injectStylesIntoStyleTag.js')}` + )}); + var content = require(${loaderUtils.stringifyRequest( + this, + `!!${request}` + )}); + + content = content.__esModule ? content.default : content; + + if (typeof content === 'string') { + content = [[module.id, content, '']]; + }` + } -var options = ${JSON.stringify(options)} +var options = ${JSON.stringify(options)}; options.insert = ${insert}; options.singleton = ${isSingleton}; -var api = require(${loaderUtils.stringifyRequest( - this, - `!${path.join(__dirname, 'runtime/injectStylesIntoStyleTag.js')}` - )}); var update = api(content, options); -if (content.locals) { - module.exports = content.locals; -} +var exported = content.locals ? content.locals : {}; + +${esModule ? 'export default' : 'module.exports ='} exported; + ${hmrCode}`; } } diff --git a/src/options.json b/src/options.json index c68ad618..76f85495 100644 --- a/src/options.json +++ b/src/options.json @@ -29,6 +29,10 @@ "base": { "description": "Sets module ID base for DLLPlugin (https://github.com/webpack-contrib/style-loader#base).", "type": "number" + }, + "esModule": { + "description": "Use the ES modules syntax (https://github.com/webpack-contrib/css-loader#esmodule).", + "type": "boolean" } }, "additionalProperties": false diff --git a/test/__snapshots__/esModule-option.test.js.snap b/test/__snapshots__/esModule-option.test.js.snap new file mode 100644 index 00000000..cf730263 --- /dev/null +++ b/test/__snapshots__/esModule-option.test.js.snap @@ -0,0 +1,799 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`"esModule" option should work when not specified and when the "injectType" option is "lazySingletonStyleTag": DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"esModule" option should work when not specified and when the "injectType" option is "lazySingletonStyleTag": errors 1`] = `Array []`; + +exports[`"esModule" option should work when not specified and when the "injectType" option is "lazySingletonStyleTag": warnings 1`] = `Array []`; + +exports[`"esModule" option should work when not specified and when the "injectType" option is "lazyStyleTag": DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"esModule" option should work when not specified and when the "injectType" option is "lazyStyleTag": errors 1`] = `Array []`; + +exports[`"esModule" option should work when not specified and when the "injectType" option is "lazyStyleTag": warnings 1`] = `Array []`; + +exports[`"esModule" option should work when not specified and when the "injectType" option is "linkTag": DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"esModule" option should work when not specified and when the "injectType" option is "linkTag": errors 1`] = `Array []`; + +exports[`"esModule" option should work when not specified and when the "injectType" option is "linkTag": warnings 1`] = `Array []`; + +exports[`"esModule" option should work when not specified and when the "injectType" option is "singletonStyleTag": DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"esModule" option should work when not specified and when the "injectType" option is "singletonStyleTag": errors 1`] = `Array []`; + +exports[`"esModule" option should work when not specified and when the "injectType" option is "singletonStyleTag": warnings 1`] = `Array []`; + +exports[`"esModule" option should work when not specified and when the "injectType" option is "styleTag": DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"esModule" option should work when not specified and when the "injectType" option is "styleTag": errors 1`] = `Array []`; + +exports[`"esModule" option should work when not specified and when the "injectType" option is "styleTag": warnings 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "lazySingletonStyleTag" and CommonJS module syntax used: DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "lazySingletonStyleTag" and CommonJS module syntax used: errors 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "lazySingletonStyleTag" and CommonJS module syntax used: warnings 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "lazySingletonStyleTag" and ES module syntax used: DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "lazySingletonStyleTag" and ES module syntax used: errors 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "lazySingletonStyleTag" and ES module syntax used: warnings 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "lazySingletonStyleTag": DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "lazySingletonStyleTag": errors 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "lazySingletonStyleTag": warnings 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "lazyStyleTag" and CommonJS module syntax used: DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "lazyStyleTag" and CommonJS module syntax used: errors 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "lazyStyleTag" and CommonJS module syntax used: warnings 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "lazyStyleTag" and ES module syntax used: DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "lazyStyleTag" and ES module syntax used: errors 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "lazyStyleTag" and ES module syntax used: warnings 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "lazyStyleTag": DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "lazyStyleTag": errors 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "lazyStyleTag": warnings 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "linkTag" and CommonJS module syntax used: DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "linkTag" and CommonJS module syntax used: errors 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "linkTag" and CommonJS module syntax used: warnings 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "linkTag" and ES module syntax used: DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "linkTag" and ES module syntax used: errors 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "linkTag" and ES module syntax used: warnings 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "linkTag": DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "linkTag": errors 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "linkTag": warnings 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "singletonStyleTag" and CommonJS module syntax used: DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "singletonStyleTag" and CommonJS module syntax used: errors 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "singletonStyleTag" and CommonJS module syntax used: warnings 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "singletonStyleTag" and ES module syntax used: DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "singletonStyleTag" and ES module syntax used: errors 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "singletonStyleTag" and ES module syntax used: warnings 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "singletonStyleTag": DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "singletonStyleTag": errors 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "singletonStyleTag": warnings 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "styleTag" and CommonJS module syntax used: DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "styleTag" and CommonJS module syntax used: errors 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "styleTag" and CommonJS module syntax used: warnings 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "styleTag" and ES module syntax used: DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "styleTag" and ES module syntax used: errors 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "styleTag" and ES module syntax used: warnings 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "styleTag": DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "styleTag": errors 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "false" and when the "injectType" option is "styleTag": warnings 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "lazySingletonStyleTag" and CommonJS module syntax used: DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "lazySingletonStyleTag" and CommonJS module syntax used: errors 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "lazySingletonStyleTag" and CommonJS module syntax used: warnings 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "lazySingletonStyleTag" and ES module syntax used: DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "lazySingletonStyleTag" and ES module syntax used: errors 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "lazySingletonStyleTag" and ES module syntax used: warnings 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "lazySingletonStyleTag": DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "lazySingletonStyleTag": errors 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "lazySingletonStyleTag": warnings 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "lazyStyleTag" and CommonJS module syntax used: DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "lazyStyleTag" and CommonJS module syntax used: errors 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "lazyStyleTag" and CommonJS module syntax used: warnings 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "lazyStyleTag" and ES module syntax used: DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "lazyStyleTag" and ES module syntax used: errors 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "lazyStyleTag" and ES module syntax used: warnings 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "lazyStyleTag": DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "lazyStyleTag": errors 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "lazyStyleTag": warnings 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "linkTag" and CommonJS module syntax used: DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "linkTag" and CommonJS module syntax used: errors 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "linkTag" and CommonJS module syntax used: warnings 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "linkTag" and ES module syntax used: DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "linkTag" and ES module syntax used: errors 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "linkTag" and ES module syntax used: warnings 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "linkTag": DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "linkTag": errors 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "linkTag": warnings 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "singletonStyleTag" and CommonJS module syntax used: DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "singletonStyleTag" and CommonJS module syntax used: errors 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "singletonStyleTag" and CommonJS module syntax used: warnings 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "singletonStyleTag" and ES module syntax used: DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "singletonStyleTag" and ES module syntax used: errors 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "singletonStyleTag" and ES module syntax used: warnings 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "singletonStyleTag": DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "singletonStyleTag": errors 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "singletonStyleTag": warnings 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "styleTag" and CommonJS module syntax used: DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "styleTag" and CommonJS module syntax used: errors 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "styleTag" and CommonJS module syntax used: warnings 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "styleTag" and ES module syntax used: DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "styleTag" and ES module syntax used: errors 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "styleTag" and ES module syntax used: warnings 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "styleTag": DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "styleTag": errors 1`] = `Array []`; + +exports[`"esModule" option should work with a value equal to "true" and when the "injectType" option is "styleTag": warnings 1`] = `Array []`; diff --git a/test/__snapshots__/validate-options.test.js.snap b/test/__snapshots__/validate-options.test.js.snap index 749d3d72..cd4bcc60 100644 --- a/test/__snapshots__/validate-options.test.js.snap +++ b/test/__snapshots__/validate-options.test.js.snap @@ -7,6 +7,12 @@ exports[`validate options should throw an error on the "attributes" option with -> Adds custom attributes to tag (https://github.com/webpack-contrib/style-loader#attributes)." `; +exports[`validate options should throw an error on the "esModule" option with "true" value 1`] = ` +"Invalid options object. Style Loader has been initialised using an options object that does not match the API schema. + - options.esModule should be a boolean. + -> Use the ES modules syntax (https://github.com/webpack-contrib/css-loader#esmodule)." +`; + exports[`validate options should throw an error on the "injectType" option with "unknown" value 1`] = ` "Invalid options object. Style Loader has been initialised using an options object that does not match the API schema. - options.injectType should be one of these: @@ -27,47 +33,47 @@ exports[`validate options should throw an error on the "insert" option with "tru exports[`validate options should throw an error on the "unknown" option with "/test/" value 1`] = ` "Invalid options object. Style Loader has been initialised using an options object that does not match the API schema. - options has an unknown property 'unknown'. These properties are valid: - object { injectType?, attributes?, insert?, base? }" + object { injectType?, attributes?, insert?, base?, esModule? }" `; exports[`validate options should throw an error on the "unknown" option with "[]" value 1`] = ` "Invalid options object. Style Loader has been initialised using an options object that does not match the API schema. - options has an unknown property 'unknown'. These properties are valid: - object { injectType?, attributes?, insert?, base? }" + object { injectType?, attributes?, insert?, base?, esModule? }" `; exports[`validate options should throw an error on the "unknown" option with "{"foo":"bar"}" value 1`] = ` "Invalid options object. Style Loader has been initialised using an options object that does not match the API schema. - options has an unknown property 'unknown'. These properties are valid: - object { injectType?, attributes?, insert?, base? }" + object { injectType?, attributes?, insert?, base?, esModule? }" `; exports[`validate options should throw an error on the "unknown" option with "{}" value 1`] = ` "Invalid options object. Style Loader has been initialised using an options object that does not match the API schema. - options has an unknown property 'unknown'. These properties are valid: - object { injectType?, attributes?, insert?, base? }" + object { injectType?, attributes?, insert?, base?, esModule? }" `; exports[`validate options should throw an error on the "unknown" option with "1" value 1`] = ` "Invalid options object. Style Loader has been initialised using an options object that does not match the API schema. - options has an unknown property 'unknown'. These properties are valid: - object { injectType?, attributes?, insert?, base? }" + object { injectType?, attributes?, insert?, base?, esModule? }" `; exports[`validate options should throw an error on the "unknown" option with "false" value 1`] = ` "Invalid options object. Style Loader has been initialised using an options object that does not match the API schema. - options has an unknown property 'unknown'. These properties are valid: - object { injectType?, attributes?, insert?, base? }" + object { injectType?, attributes?, insert?, base?, esModule? }" `; exports[`validate options should throw an error on the "unknown" option with "test" value 1`] = ` "Invalid options object. Style Loader has been initialised using an options object that does not match the API schema. - options has an unknown property 'unknown'. These properties are valid: - object { injectType?, attributes?, insert?, base? }" + object { injectType?, attributes?, insert?, base?, esModule? }" `; exports[`validate options should throw an error on the "unknown" option with "true" value 1`] = ` "Invalid options object. Style Loader has been initialised using an options object that does not match the API schema. - options has an unknown property 'unknown'. These properties are valid: - object { injectType?, attributes?, insert?, base? }" + object { injectType?, attributes?, insert?, base?, esModule? }" `; diff --git a/test/esModule-option.test.js b/test/esModule-option.test.js new file mode 100644 index 00000000..a052afc1 --- /dev/null +++ b/test/esModule-option.test.js @@ -0,0 +1,209 @@ +import path from 'path'; + +import { + compile, + getCompiler, + getEntryByInjectType, + getErrors, + getWarnings, + runInJsDom, +} from './helpers/index'; + +describe('"esModule" option', () => { + const injectTypes = [ + 'styleTag', + 'singletonStyleTag', + 'lazyStyleTag', + 'lazySingletonStyleTag', + 'linkTag', + ]; + + injectTypes.forEach((injectType) => { + it(`should work when not specified and when the "injectType" option is "${injectType}"`, async () => { + const entry = getEntryByInjectType('simple.js', injectType); + const compiler = getCompiler(entry, { injectType }); + 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'); + }); + + it(`should work with a value equal to "true" and when the "injectType" option is "${injectType}"`, async () => { + const entry = getEntryByInjectType('simple.js', injectType); + const compiler = getCompiler(entry, { injectType, esModule: true }); + 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'); + }); + + it(`should work with a value equal to "true" and when the "injectType" option is "${injectType}" and ES module syntax used`, async () => { + const entry = getEntryByInjectType('simple.js', injectType); + const compiler = getCompiler( + entry, + { injectType }, + { + module: { + rules: [ + { + test: /\.css$/i, + use: [ + { + loader: path.resolve(__dirname, '../src/cjs.js'), + options: { injectType, esModule: true }, + }, + injectType === 'linkTag' + ? { loader: 'file-loader', options: { esModule: true } } + : { loader: 'css-loader', options: { esModule: true } }, + ], + }, + ], + }, + } + ); + 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'); + }); + + it(`should work with a value equal to "true" and when the "injectType" option is "${injectType}" and CommonJS module syntax used`, async () => { + const entry = getEntryByInjectType('simple.js', injectType); + const compiler = getCompiler( + entry, + { injectType }, + { + module: { + rules: [ + { + test: /\.css$/i, + use: [ + { + loader: path.resolve(__dirname, '../src/cjs.js'), + options: { injectType, esModule: true }, + }, + injectType === 'linkTag' + ? { + loader: 'file-loader', + options: { esModule: false }, + } + : { + loader: 'css-loader', + options: { esModule: false }, + }, + ], + }, + ], + }, + } + ); + 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'); + }); + + it(`should work with a value equal to "false" and when the "injectType" option is "${injectType}"`, async () => { + const entry = getEntryByInjectType('simple.js', injectType); + const compiler = getCompiler(entry, { injectType, esModule: false }); + 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'); + }); + + it(`should work with a value equal to "false" and when the "injectType" option is "${injectType}" and ES module syntax used`, async () => { + const entry = getEntryByInjectType('simple.js', injectType); + const compiler = getCompiler( + entry, + { injectType }, + { + module: { + rules: [ + { + test: /\.css$/i, + use: [ + { + loader: path.resolve(__dirname, '../src/cjs.js'), + options: { injectType, esModule: false }, + }, + injectType === 'linkTag' + ? { loader: 'file-loader', options: { esModule: true } } + : { loader: 'css-loader', options: { esModule: true } }, + ], + }, + ], + }, + } + ); + 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'); + }); + + it(`should work with a value equal to "false" and when the "injectType" option is "${injectType}" and CommonJS module syntax used`, async () => { + const entry = getEntryByInjectType('simple.js', injectType); + const compiler = getCompiler( + entry, + { injectType }, + { + module: { + rules: [ + { + test: /\.css$/i, + use: [ + { + loader: path.resolve(__dirname, '../src/cjs.js'), + options: { injectType, esModule: false }, + }, + injectType === 'linkTag' + ? { + loader: 'file-loader', + options: { esModule: false }, + } + : { + loader: 'css-loader', + options: { esModule: false }, + }, + ], + }, + ], + }, + } + ); + 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'); + }); + }); +}); diff --git a/test/manual/webpack.config.js b/test/manual/webpack.config.js index f66938a9..74afa9f9 100644 --- a/test/manual/webpack.config.js +++ b/test/manual/webpack.config.js @@ -10,6 +10,11 @@ const ENABLE_ES_MODULE = ? Boolean(process.env.ES_MODULE) : false; +const ENABLE_PREVIOUS_ES_MODULE = + typeof process.env.PREVIOUS_ES_MODULE !== 'undefined' + ? Boolean(process.env.PREVIOUS_ES_MODULE) + : false; + module.exports = { devtool: ENABLE_SOURCE_MAP ? 'source-map' : false, mode: 'development', @@ -29,12 +34,13 @@ module.exports = { use: [ { loader: require.resolve('../../dist/cjs.js'), + options: { esModule: ENABLE_ES_MODULE }, }, { loader: 'css-loader', options: { sourceMap: ENABLE_SOURCE_MAP, - esModule: ENABLE_ES_MODULE, + esModule: ENABLE_PREVIOUS_ES_MODULE, }, }, ], @@ -45,12 +51,13 @@ module.exports = { use: [ { loader: require.resolve('../../dist/cjs.js'), + options: { esModule: ENABLE_ES_MODULE }, }, { loader: 'css-loader', options: { sourceMap: ENABLE_SOURCE_MAP, - esModule: ENABLE_ES_MODULE, + esModule: ENABLE_PREVIOUS_ES_MODULE, modules: true, }, }, @@ -61,13 +68,13 @@ module.exports = { use: [ { loader: require.resolve('../../dist/cjs.js'), - options: { injectType: 'lazyStyleTag' }, + options: { injectType: 'lazyStyleTag', esModule: ENABLE_ES_MODULE }, }, { loader: 'css-loader', options: { sourceMap: ENABLE_SOURCE_MAP, - esModule: ENABLE_ES_MODULE, + esModule: ENABLE_PREVIOUS_ES_MODULE, }, }, ], @@ -77,13 +84,13 @@ module.exports = { use: [ { loader: require.resolve('../../dist/cjs.js'), - options: { injectType: 'lazyStyleTag' }, + options: { injectType: 'lazyStyleTag', esModule: ENABLE_ES_MODULE }, }, { loader: 'css-loader', options: { sourceMap: ENABLE_SOURCE_MAP, - esModule: ENABLE_ES_MODULE, + esModule: ENABLE_PREVIOUS_ES_MODULE, modules: true, }, }, @@ -95,10 +102,11 @@ module.exports = { use: [ { loader: require.resolve('../../dist/cjs.js'), - options: { injectType: 'linkTag' }, + options: { injectType: 'linkTag', esModule: ENABLE_ES_MODULE }, }, { loader: 'file-loader', + options: { esModule: ENABLE_PREVIOUS_ES_MODULE }, }, ], }, @@ -108,12 +116,13 @@ module.exports = { use: [ { loader: require.resolve('../../dist/cjs.js'), + options: { esModule: ENABLE_ES_MODULE }, }, { loader: 'css-loader', options: { sourceMap: ENABLE_SOURCE_MAP, - esModule: ENABLE_ES_MODULE, + esModule: ENABLE_PREVIOUS_ES_MODULE, }, }, { @@ -131,13 +140,13 @@ module.exports = { use: [ { loader: require.resolve('../../dist/cjs.js'), - options: { injectType: 'lazyStyleTag' }, + options: { injectType: 'lazyStyleTag', esModule: ENABLE_ES_MODULE }, }, { loader: 'css-loader', options: { sourceMap: ENABLE_SOURCE_MAP, - esModule: ENABLE_ES_MODULE, + esModule: ENABLE_PREVIOUS_ES_MODULE, }, }, { diff --git a/test/validate-options.test.js b/test/validate-options.test.js index 940cb836..b066a5a7 100644 --- a/test/validate-options.test.js +++ b/test/validate-options.test.js @@ -20,6 +20,10 @@ describe('validate options', () => { success: ['selector', () => {}], failure: [true], }, + esModule: { + success: [true, false], + failure: ['true'], + }, unknown: { success: [], failure: [1, true, false, 'test', /test/, [], {}, { foo: 'bar' }],