diff --git a/packages/rspack/etc/api.md b/packages/rspack/etc/api.md index 25122c36dc04..3f03a1d8d3a3 100644 --- a/packages/rspack/etc/api.md +++ b/packages/rspack/etc/api.md @@ -1570,6 +1570,8 @@ const cssChunkFilename: z.ZodUnion<[z.ZodString, z.ZodFunction - `\nexport var ${key} = ${stringifyLocal( + ([id, key]) => + `\nvar ${id} = ${stringifyLocal( /** @type {Locals} */ locals[key] )};` ) - .join("") - : `\n${ - esModule ? "export default" : "module.exports =" - } ${JSON.stringify(locals)};` - : esModule - ? `\nexport {};` - : ""; + .join(""); + const exportsString = `export { ${identifiers + .map(([id, key]) => `${id} as ${JSON.stringify(key)}`) + .join(", ")} }`; + + const defaultExport = + typeof options.defaultExport !== "undefined" + ? options.defaultExport + : false; + + return defaultExport + ? `${localsString}\n${exportsString}\nexport default { ${identifiers + .map(([id, key]) => `${JSON.stringify(key)}: ${id}`) + .join(", ")} }\n` + : `${localsString}\n${exportsString}\n`; + } + + return `\n${ + esModule ? "export default" : "module.exports = " + } ${JSON.stringify(locals)};`; + } else if (esModule) { + return "\nexport {};"; + } + return ""; + })(); let resultSource = `// extracted by ${CssExtractRspackPlugin.pluginName}`; diff --git a/plugin-test/css-extract/cases/custom-loader-with-functional-exports/expected/main.js b/plugin-test/css-extract/cases/custom-loader-with-functional-exports/expected/main.js index e87d387f004d..9e1dfd7e45e5 100644 --- a/plugin-test/css-extract/cases/custom-loader-with-functional-exports/expected/main.js +++ b/plugin-test/css-extract/cases/custom-loader-with-functional-exports/expected/main.js @@ -4,12 +4,13 @@ var __webpack_modules__ = ({ "./style.css?3e20": (function (__unused_webpack_module, __webpack_exports__, __webpack_require__) { __webpack_require__.r(__webpack_exports__); __webpack_require__.d(__webpack_exports__, { - cnA: function() { return cnA; }, - cnB: function() { return cnB; } + cnA: function() { return _1; }, + cnB: function() { return _2; } }); // extracted by css-extract-rspack-plugin -var cnA = ()=>"class-name-a"; -var cnB = ()=>"class-name-b"; +var _1 = ()=>"class-name-a"; +var _2 = ()=>"class-name-b"; + }), }); diff --git a/plugin-test/css-extract/cases/es-named-export-as-is-output-module/expected/main.css b/plugin-test/css-extract/cases/es-named-export-as-is-output-module/expected/main.css new file mode 100644 index 000000000000..b9a7e294868f --- /dev/null +++ b/plugin-test/css-extract/cases/es-named-export-as-is-output-module/expected/main.css @@ -0,0 +1,12 @@ +.Xh041yLR4iCP4RGjge50 { + background: red; +} + +.NMuRsxoDwvW8BhSXhFAY { + color: green; +} + +.ayWIv09rPsAqE2JznIsI { + color: blue; +} + diff --git a/plugin-test/css-extract/cases/es-named-export-as-is-output-module/expected/main.mjs b/plugin-test/css-extract/cases/es-named-export-as-is-output-module/expected/main.mjs new file mode 100644 index 000000000000..04e49ce4be37 --- /dev/null +++ b/plugin-test/css-extract/cases/es-named-export-as-is-output-module/expected/main.mjs @@ -0,0 +1,86 @@ +var __webpack_modules__ = ({ +"./style.css?eccb": (function (__unused_webpack_module, __webpack_exports__, __webpack_require__) { +__webpack_require__.r(__webpack_exports__); +__webpack_require__.d(__webpack_exports__, { + "a-class": function() { return _1; }, + b__class: function() { return _2; }, + cClass: function() { return _3; } +}); +// extracted by css-extract-rspack-plugin +var _1 = "Xh041yLR4iCP4RGjge50"; +var _2 = "NMuRsxoDwvW8BhSXhFAY"; +var _3 = "ayWIv09rPsAqE2JznIsI"; + +}), + +}); +/************************************************************************/ +// The module cache +var __webpack_module_cache__ = {}; + +// The require function +function __webpack_require__(moduleId) { + +// Check if module is in cache +var cachedModule = __webpack_module_cache__[moduleId]; +if (cachedModule !== undefined) { +return cachedModule.exports; +} +// Create a new module (and put it into the cache) +var module = (__webpack_module_cache__[moduleId] = { +exports: {} +}); +// Execute the module function +__webpack_modules__[moduleId](module, module.exports, __webpack_require__); + +// Return the exports of the module +return module.exports; + +} + +/************************************************************************/ +// webpack/runtime/define_property_getters +(() => { +__webpack_require__.d = function(exports, definition) { + for(var key in definition) { + if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { + Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); + } + } +}; +})(); +// webpack/runtime/has_own_property +(() => { +__webpack_require__.o = function (obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); +}; + +})(); +// webpack/runtime/make_namespace_object +(() => { +// define __esModule on exports +__webpack_require__.r = function(exports) { + if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { + Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); + } + Object.defineProperty(exports, '__esModule', { value: true }); +}; + +})(); +/************************************************************************/ +var __webpack_exports__ = {}; +// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. +(() => { +__webpack_require__.r(__webpack_exports__); +/* harmony import */var _style_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./style.css?eccb"); + +// eslint-disable-next-line no-console +console.log({ + css: _style_css__WEBPACK_IMPORTED_MODULE_0__["default"], + aClass: _style_css__WEBPACK_IMPORTED_MODULE_0__["a-class"], + bClass: _style_css__WEBPACK_IMPORTED_MODULE_0__.b__class, + cClass: _style_css__WEBPACK_IMPORTED_MODULE_0__.cClass +}); + +})(); + diff --git a/plugin-test/css-extract/cases/es-named-export-as-is-output-module/index.js b/plugin-test/css-extract/cases/es-named-export-as-is-output-module/index.js new file mode 100644 index 000000000000..aa114287a3de --- /dev/null +++ b/plugin-test/css-extract/cases/es-named-export-as-is-output-module/index.js @@ -0,0 +1,8 @@ +import css, { + "a-class" as aClass, + "b__class" as bClass, + cClass, +} from "./style.css"; + +// eslint-disable-next-line no-console +console.log({ css, aClass, bClass, cClass }); diff --git a/plugin-test/css-extract/cases/es-named-export-as-is-output-module/style.css b/plugin-test/css-extract/cases/es-named-export-as-is-output-module/style.css new file mode 100644 index 000000000000..a90854085783 --- /dev/null +++ b/plugin-test/css-extract/cases/es-named-export-as-is-output-module/style.css @@ -0,0 +1,11 @@ +.a-class { + background: red; +} + +.b__class { + color: green; +} + +.cClass { + color: blue; +} diff --git a/plugin-test/css-extract/cases/es-named-export-as-is-output-module/webpack.config.js b/plugin-test/css-extract/cases/es-named-export-as-is-output-module/webpack.config.js new file mode 100644 index 000000000000..4b321750f80c --- /dev/null +++ b/plugin-test/css-extract/cases/es-named-export-as-is-output-module/webpack.config.js @@ -0,0 +1,38 @@ +const Self = require("@rspack/core").CssExtractRspackPlugin; + +module.exports = { + entry: "./index.js", + module: { + rules: [ + { + test: /\.css$/, + use: [ + { + loader: Self.loader, + }, + { + loader: "css-loader", + options: { + esModule: true, + modules: { + namedExport: true, + exportLocalsConvention: "asIs", + }, + }, + }, + ], + }, + ], + }, + output: { + module: true, + }, + experiments: { + outputModule: true, + }, + plugins: [ + new Self({ + filename: "[name].css", + }), + ], +}; diff --git a/plugin-test/css-extract/cases/es-named-export-as-is/expected/main.css b/plugin-test/css-extract/cases/es-named-export-as-is/expected/main.css new file mode 100644 index 000000000000..b9a7e294868f --- /dev/null +++ b/plugin-test/css-extract/cases/es-named-export-as-is/expected/main.css @@ -0,0 +1,12 @@ +.Xh041yLR4iCP4RGjge50 { + background: red; +} + +.NMuRsxoDwvW8BhSXhFAY { + color: green; +} + +.ayWIv09rPsAqE2JznIsI { + color: blue; +} + diff --git a/plugin-test/css-extract/cases/es-named-export-as-is/expected/main.js b/plugin-test/css-extract/cases/es-named-export-as-is/expected/main.js new file mode 100644 index 000000000000..ebeb45782932 --- /dev/null +++ b/plugin-test/css-extract/cases/es-named-export-as-is/expected/main.js @@ -0,0 +1,90 @@ +(() => { // webpackBootstrap +"use strict"; +var __webpack_modules__ = ({ +"./style.css?eccb": (function (__unused_webpack_module, __webpack_exports__, __webpack_require__) { +__webpack_require__.r(__webpack_exports__); +__webpack_require__.d(__webpack_exports__, { + "a-class": function() { return _1; }, + b__class: function() { return _2; }, + cClass: function() { return _3; } +}); +// extracted by css-extract-rspack-plugin +var _1 = "Xh041yLR4iCP4RGjge50"; +var _2 = "NMuRsxoDwvW8BhSXhFAY"; +var _3 = "ayWIv09rPsAqE2JznIsI"; + +}), + +}); +/************************************************************************/ +// The module cache +var __webpack_module_cache__ = {}; + +// The require function +function __webpack_require__(moduleId) { + +// Check if module is in cache +var cachedModule = __webpack_module_cache__[moduleId]; +if (cachedModule !== undefined) { +return cachedModule.exports; +} +// Create a new module (and put it into the cache) +var module = (__webpack_module_cache__[moduleId] = { +exports: {} +}); +// Execute the module function +__webpack_modules__[moduleId](module, module.exports, __webpack_require__); + +// Return the exports of the module +return module.exports; + +} + +/************************************************************************/ +// webpack/runtime/define_property_getters +(() => { +__webpack_require__.d = function(exports, definition) { + for(var key in definition) { + if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { + Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); + } + } +}; +})(); +// webpack/runtime/has_own_property +(() => { +__webpack_require__.o = function (obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); +}; + +})(); +// webpack/runtime/make_namespace_object +(() => { +// define __esModule on exports +__webpack_require__.r = function(exports) { + if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { + Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); + } + Object.defineProperty(exports, '__esModule', { value: true }); +}; + +})(); +/************************************************************************/ +var __webpack_exports__ = {}; +// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. +(() => { +__webpack_require__.r(__webpack_exports__); +/* harmony import */var _style_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./style.css?eccb"); + +// eslint-disable-next-line no-console +console.log({ + css: _style_css__WEBPACK_IMPORTED_MODULE_0__["default"], + aClass: _style_css__WEBPACK_IMPORTED_MODULE_0__["a-class"], + bClass: _style_css__WEBPACK_IMPORTED_MODULE_0__.b__class, + cClass: _style_css__WEBPACK_IMPORTED_MODULE_0__.cClass +}); + +})(); + +})() +; \ No newline at end of file diff --git a/plugin-test/css-extract/cases/es-named-export-as-is/index.js b/plugin-test/css-extract/cases/es-named-export-as-is/index.js new file mode 100644 index 000000000000..aa114287a3de --- /dev/null +++ b/plugin-test/css-extract/cases/es-named-export-as-is/index.js @@ -0,0 +1,8 @@ +import css, { + "a-class" as aClass, + "b__class" as bClass, + cClass, +} from "./style.css"; + +// eslint-disable-next-line no-console +console.log({ css, aClass, bClass, cClass }); diff --git a/plugin-test/css-extract/cases/es-named-export-as-is/style.css b/plugin-test/css-extract/cases/es-named-export-as-is/style.css new file mode 100644 index 000000000000..a90854085783 --- /dev/null +++ b/plugin-test/css-extract/cases/es-named-export-as-is/style.css @@ -0,0 +1,11 @@ +.a-class { + background: red; +} + +.b__class { + color: green; +} + +.cClass { + color: blue; +} diff --git a/plugin-test/css-extract/cases/es-named-export-as-is/webpack.config.js b/plugin-test/css-extract/cases/es-named-export-as-is/webpack.config.js new file mode 100644 index 000000000000..e4cf9be851e1 --- /dev/null +++ b/plugin-test/css-extract/cases/es-named-export-as-is/webpack.config.js @@ -0,0 +1,32 @@ +const Self = require("@rspack/core").CssExtractRspackPlugin; + +module.exports = { + entry: "./index.js", + module: { + rules: [ + { + test: /\.css$/, + use: [ + { + loader: Self.loader, + }, + { + loader: "css-loader", + options: { + esModule: true, + modules: { + namedExport: true, + exportLocalsConvention: "asIs", + }, + }, + }, + ], + }, + ], + }, + plugins: [ + new Self({ + filename: "[name].css", + }), + ], +}; diff --git a/plugin-test/css-extract/cases/es-named-export-output-module/expected/main.mjs b/plugin-test/css-extract/cases/es-named-export-output-module/expected/main.mjs index 29d619c02d0d..527ddb7bc336 100644 --- a/plugin-test/css-extract/cases/es-named-export-output-module/expected/main.mjs +++ b/plugin-test/css-extract/cases/es-named-export-output-module/expected/main.mjs @@ -2,14 +2,15 @@ var __webpack_modules__ = ({ "./style.css?eccb": (function (__unused_webpack_module, __webpack_exports__, __webpack_require__) { __webpack_require__.r(__webpack_exports__); __webpack_require__.d(__webpack_exports__, { - aClass: function() { return aClass; }, - bClass: function() { return bClass; }, - cClass: function() { return cClass; } + aClass: function() { return _1; }, + bClass: function() { return _2; }, + cClass: function() { return _3; } }); // extracted by css-extract-rspack-plugin -var aClass = "foo__style__a-class"; -var bClass = "foo__style__b__class"; -var cClass = "foo__style__cClass"; +var _1 = "foo__style__a-class"; +var _2 = "foo__style__b__class"; +var _3 = "foo__style__cClass"; + }), }); diff --git a/plugin-test/css-extract/cases/es-named-export/expected/main.js b/plugin-test/css-extract/cases/es-named-export/expected/main.js index 71d67323c69a..0a825f7c4c26 100644 --- a/plugin-test/css-extract/cases/es-named-export/expected/main.js +++ b/plugin-test/css-extract/cases/es-named-export/expected/main.js @@ -4,14 +4,15 @@ var __webpack_modules__ = ({ "./style.css?eccb": (function (__unused_webpack_module, __webpack_exports__, __webpack_require__) { __webpack_require__.r(__webpack_exports__); __webpack_require__.d(__webpack_exports__, { - aClass: function() { return aClass; }, - bClass: function() { return bClass; }, - cClass: function() { return cClass; } + "a-class": function() { return _1; }, + b__class: function() { return _2; }, + cClass: function() { return _3; } }); // extracted by css-extract-rspack-plugin -var aClass = "foo__style__a-class"; -var bClass = "foo__style__b__class"; -var cClass = "foo__style__cClass"; +var _1 = "foo__style__a-class"; +var _2 = "foo__style__b__class"; +var _3 = "foo__style__cClass"; + }), }); diff --git a/plugin-test/css-extract/cases/es-named-export/webpack.config.js b/plugin-test/css-extract/cases/es-named-export/webpack.config.js index d86536a29375..83379072c343 100644 --- a/plugin-test/css-extract/cases/es-named-export/webpack.config.js +++ b/plugin-test/css-extract/cases/es-named-export/webpack.config.js @@ -16,6 +16,7 @@ module.exports = { esModule: true, modules: { namedExport: true, + exportLocalsConvention: "asIs", localIdentName: "foo__[name]__[local]" } } diff --git a/plugin-test/css-extract/cases/export-only-locals-and-es-named-export/expected/main.js b/plugin-test/css-extract/cases/export-only-locals-and-es-named-export/expected/main.js index 02b8678a306c..cb390ed32095 100644 --- a/plugin-test/css-extract/cases/export-only-locals-and-es-named-export/expected/main.js +++ b/plugin-test/css-extract/cases/export-only-locals-and-es-named-export/expected/main.js @@ -4,14 +4,15 @@ var __webpack_modules__ = ({ "./style.css": (function (__unused_webpack_module, __webpack_exports__, __webpack_require__) { __webpack_require__.r(__webpack_exports__); __webpack_require__.d(__webpack_exports__, { - aClass: function() { return aClass; }, - bClass: function() { return bClass; }, - cClass: function() { return cClass; } + aClass: function() { return _1; }, + bClass: function() { return _2; }, + cClass: function() { return _3; } }); // extracted by css-extract-rspack-plugin -var aClass = "foo__style__a-class"; -var bClass = "foo__style__b__class"; -var cClass = "foo__style__cClass"; +var _1 = "foo__style__a-class"; +var _2 = "foo__style__b__class"; +var _3 = "foo__style__cClass"; + }), });