diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 624a871f..71abb2bf 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -67,7 +67,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] - node-version: [12.x, 14.x, 16.x, 18.x, 20.x] + node-version: [12.x, 14.x, 16.x, 18.x, 20.x, 22.x] webpack-version: [latest] runs-on: ${{ matrix.os }} @@ -82,11 +82,21 @@ jobs: run: git config --global core.autocrlf input - uses: actions/checkout@v4 - + - uses: actions/github-script@v7 + id: calculate_architecture + with: + result-encoding: string + script: | + if ('${{ matrix.os }}' === 'macos-latest' && ('${{ matrix['node-version'] }}' === '12.x' || '${{ matrix['node-version'] }}' === '14.x')) { + return "x64" + } else { + return '' + } - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} + architecture: ${{ steps.calculate_architecture.outputs.result }} cache: "npm" - name: Install dependencies @@ -110,7 +120,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] - node-version: [12.x, 14.x, 16.x, 18.x, 20.x] + node-version: [12.x, 14.x, 16.x, 18.x, 20.x, 22.x] runs-on: ${{ matrix.os }} @@ -120,11 +130,21 @@ jobs: run: git config --global core.autocrlf input - uses: actions/checkout@v4 - + - uses: actions/github-script@v7 + id: calculate_architecture + with: + result-encoding: string + script: | + if ('${{ matrix.os }}' === 'macos-latest' && ('${{ matrix['node-version'] }}' === '12.x' || '${{ matrix['node-version'] }}' === '14.x')) { + return "x64" + } else { + return '' + } - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} + architecture: ${{ steps.calculate_architecture.outputs.result }} cache: "npm" - name: Install dependencies diff --git a/CHANGELOG.md b/CHANGELOG.md index 93dc97fd..84831237 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [2.9.1](https://github.com/webpack-contrib/mini-css-extract-plugin/compare/v2.9.0...v2.9.1) (2024-08-19) + + +### Bug Fixes + +* add `export default {}` when CSS modules enabled and a file is empty for the `defaultExport` option ([8f77e19](https://github.com/webpack-contrib/mini-css-extract-plugin/commit/8f77e19a89eca97b05f1855d2c851592e98ff774)) + ## [2.9.0](https://github.com/webpack-contrib/mini-css-extract-plugin/compare/v2.8.1...v2.9.0) (2024-04-16) diff --git a/README.md b/README.md index 42c3e674..a5a6c458 100644 --- a/README.md +++ b/README.md @@ -82,11 +82,11 @@ module.exports = { }; ``` -> **Warning** +> [!WARNING] > > Note that if you import CSS from your webpack entrypoint or import styles in the [initial](https://webpack.js.org/concepts/under-the-hood/#chunks) chunk, `mini-css-extract-plugin` will not load this CSS into the page. Please use [`html-webpack-plugin`](https://github.com/jantimon/html-webpack-plugin) for automatic generation `link` tags or create `index.html` file with `link` tag. -> **Warning** +> [!WARNING] > > Source maps works only for `source-map`/`nosources-source-map`/`hidden-nosources-source-map`/`hidden-source-map` values because CSS only supports source maps with the `sourceMappingURL` comment (i.e. `//# sourceMappingURL=style.css.map`). If you need set `devtool` to another value you can enable source maps generation for extracted CSS using [`sourceMap: true`](https://github.com/webpack-contrib/css-loader#sourcemap) for `css-loader`. @@ -162,7 +162,7 @@ Default: `document.head.appendChild(linkTag);` Inserts the `link` tag at the given position for [non-initial (async)](https://webpack.js.org/concepts/under-the-hood/#chunks) CSS chunks -> **Warning** +> [!WARNING] > > Only for [non-initial (async)](https://webpack.js.org/concepts/under-the-hood/#chunks) chunks. @@ -222,7 +222,7 @@ type attributes = Record}; Default: `{}` -> **Warning** +> [!WARNING] > > Only for [non-initial (async)](https://webpack.js.org/concepts/under-the-hood/#chunks) chunks. @@ -253,7 +253,7 @@ module.exports = { }; ``` -> **Note** +> [!NOTE] > > It's only applied to dynamically loaded css chunks, if you want to modify link attributes inside html file, please using [html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin) @@ -560,7 +560,7 @@ type defaultExport = boolean; Default: `false` -> **Note** +> [!NOTE] > > This option will work only when you set `namedExport` to `true` in `css-loader` @@ -592,9 +592,11 @@ module.exports = { }, { loader: "css-loader", - esModule: true, - modules: { - namedExport: true, + options: { + esModule: true, + modules: { + namedExport: true, + }, }, }, ], @@ -830,7 +832,7 @@ module.exports = { ### Hot Module Reloading (HMR) -> **Note** +> [!NOTE] > > HMR is automatically supported in webpack 5. No need to configure it. Skip the following: diff --git a/package-lock.json b/package-lock.json index fdf1b2e1..58daef93 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mini-css-extract-plugin", - "version": "2.9.0", + "version": "2.9.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mini-css-extract-plugin", - "version": "2.9.0", + "version": "2.9.1", "license": "MIT", "dependencies": { "schema-utils": "^4.0.0", diff --git a/package.json b/package.json index 56358eb0..ef5701b2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mini-css-extract-plugin", - "version": "2.9.0", + "version": "2.9.1", "description": "extracts CSS into separate files", "license": "MIT", "repository": "webpack-contrib/mini-css-extract-plugin", diff --git a/src/loader.js b/src/loader.js index 5c0b04b1..e4217f5c 100644 --- a/src/loader.js +++ b/src/loader.js @@ -255,6 +255,11 @@ function pitch(request) { } const result = (function makeResult() { + const defaultExport = + typeof options.defaultExport !== "undefined" + ? options.defaultExport + : false; + if (locals) { if (namedExport) { const identifiers = Array.from( @@ -281,11 +286,6 @@ function pitch(request) { .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}`) @@ -297,7 +297,9 @@ function pitch(request) { esModule ? "export default" : "module.exports = " } ${JSON.stringify(locals)};`; } else if (esModule) { - return "\nexport {};"; + return defaultExport + ? "\nexport {};export default {};" + : "\nexport {};"; } return ""; })(); diff --git a/test/cases/es-named-and-default-export-1/empty.css b/test/cases/es-named-and-default-export-1/empty.css new file mode 100644 index 00000000..e69de29b diff --git a/test/cases/es-named-and-default-export-1/expected/main.css b/test/cases/es-named-and-default-export-1/expected/main.css new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/test/cases/es-named-and-default-export-1/expected/main.css @@ -0,0 +1 @@ + diff --git a/test/cases/es-named-and-default-export-1/expected/main.js b/test/cases/es-named-and-default-export-1/expected/main.js new file mode 100644 index 00000000..1d321d3a --- /dev/null +++ b/test/cases/es-named-and-default-export-1/expected/main.js @@ -0,0 +1,85 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ var __webpack_modules__ = ([ +/* 0 */, +/* 1 */ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) +/* harmony export */ }); +// extracted by mini-css-extract-plugin +/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({}); + +/***/ }) +/******/ ]); +/************************************************************************/ +/******/ // 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] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ 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 */ +/******/ (() => { +/******/ // define getter functions for harmony exports +/******/ __webpack_require__.d = (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/hasOwnProperty shorthand */ +/******/ (() => { +/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) +/******/ })(); +/******/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (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 _empty_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); + + +// eslint-disable-next-line no-console +console.log({ css: _empty_css__WEBPACK_IMPORTED_MODULE_0__["default"] }); + +})(); + +/******/ })() +; \ No newline at end of file diff --git a/test/cases/es-named-and-default-export-1/index.js b/test/cases/es-named-and-default-export-1/index.js new file mode 100644 index 00000000..e42dfb9a --- /dev/null +++ b/test/cases/es-named-and-default-export-1/index.js @@ -0,0 +1,4 @@ +import css from "./empty.css"; + +// eslint-disable-next-line no-console +console.log({ css }); diff --git a/test/cases/es-named-and-default-export-1/webpack.config.js b/test/cases/es-named-and-default-export-1/webpack.config.js new file mode 100644 index 00000000..b58d12f5 --- /dev/null +++ b/test/cases/es-named-and-default-export-1/webpack.config.js @@ -0,0 +1,34 @@ +import Self from "../../../src"; + +module.exports = { + entry: "./index.js", + module: { + rules: [ + { + test: /\.css$/, + use: [ + { + loader: Self.loader, + options: { + defaultExport: true, + }, + }, + { + loader: "css-loader", + options: { + esModule: true, + modules: { + namedExport: true, + }, + }, + }, + ], + }, + ], + }, + plugins: [ + new Self({ + filename: "[name].css", + }), + ], +};