From 8b273d15f9ca2baf7cd0e3c03817e74be7221e5b Mon Sep 17 00:00:00 2001 From: Alexander Akait <4567934+alexander-akait@users.noreply.github.com> Date: Thu, 11 Dec 2025 23:39:22 +0300 Subject: [PATCH 1/2] fix: handle empty files (#295) --- src/index.js | 2 +- src/utils.js | 15 ---------- test/CssMinimizerPlugin.test.js | 28 +++++++++++++++++++ .../CssMinimizerPlugin.test.js.snap | 20 +++++++++++++ test/__snapshots__/minify-option.test.js.snap | 10 +------ test/fixtures/empty.css | 1 + test/fixtures/empty.js | 1 + test/helpers/getCompiler.js | 2 +- 8 files changed, 53 insertions(+), 26 deletions(-) create mode 100644 test/fixtures/empty.css create mode 100644 test/fixtures/empty.js diff --git a/src/index.js b/src/index.js index 7f544e4..30d53a8 100644 --- a/src/index.js +++ b/src/index.js @@ -622,7 +622,7 @@ class CssMinimizerPlugin { innerSourceMap, true, ); - } else if (item.code) { + } else if (typeof item.code !== "undefined" && item.code !== null) { output.source = new RawSource(item.code); } } diff --git a/src/utils.js b/src/utils.js index 09ccb82..89ccbf8 100644 --- a/src/utils.js +++ b/src/utils.js @@ -20,21 +20,6 @@ const notSettled = Symbol("not-settled"); * @returns {Promise} A promise that fulfills to an array of the results */ function throttleAll(limit, tasks) { - if (!Number.isInteger(limit) || limit < 1) { - throw new TypeError( - `Expected \`limit\` to be a finite number > 0, got \`${limit}\` (${typeof limit})`, - ); - } - - if ( - !Array.isArray(tasks) || - !tasks.every((task) => typeof task === "function") - ) { - throw new TypeError( - "Expected `tasks` to be a list of functions returning a promise", - ); - } - return new Promise((resolve, reject) => { const result = Array.from({ length: tasks.length }).fill(notSettled); const entries = tasks.entries(); diff --git a/test/CssMinimizerPlugin.test.js b/test/CssMinimizerPlugin.test.js index 70ba3bb..c02d856 100644 --- a/test/CssMinimizerPlugin.test.js +++ b/test/CssMinimizerPlugin.test.js @@ -239,6 +239,34 @@ describe("CssMinimizerPlugin", () => { ).toMatchSnapshot(); }); + it("should work", async () => { + const compiler = getCompiler({ + entry: path.join(__dirname, "fixtures", "entry.js"), + }); + + new CssMinimizerPlugin().apply(compiler); + + const stats = await compile(compiler); + + expect(readAssets(compiler, stats, /\.css$/)).toMatchSnapshot("assets"); + expect(getErrors(stats)).toMatchSnapshot("errors"); + expect(getWarnings(stats)).toMatchSnapshot("warnings"); + }); + + it("should work with empty files", async () => { + const compiler = getCompiler({ + entry: path.join(__dirname, "fixtures", "empty.js"), + }); + + new CssMinimizerPlugin().apply(compiler); + + const stats = await compile(compiler); + + expect(readAssets(compiler, stats, /\.css$/)).toMatchSnapshot("assets"); + expect(getErrors(stats)).toMatchSnapshot("errors"); + expect(getWarnings(stats)).toMatchSnapshot("warnings"); + }); + it("should build error", () => { const compiler = getCompiler({ entry: { diff --git a/test/__snapshots__/CssMinimizerPlugin.test.js.snap b/test/__snapshots__/CssMinimizerPlugin.test.js.snap index fd2bc96..dcf0fb8 100644 --- a/test/__snapshots__/CssMinimizerPlugin.test.js.snap +++ b/test/__snapshots__/CssMinimizerPlugin.test.js.snap @@ -232,6 +232,16 @@ exports[`CssMinimizerPlugin should work with child compilation: errors 1`] = `[] exports[`CssMinimizerPlugin should work with child compilation: warnings 1`] = `[]`; +exports[`CssMinimizerPlugin should work with empty files: assets 1`] = ` +{ + "main.css": "", +} +`; + +exports[`CssMinimizerPlugin should work with empty files: errors 1`] = `[]`; + +exports[`CssMinimizerPlugin should work with empty files: warnings 1`] = `[]`; + exports[`CssMinimizerPlugin should work with source map and use memory cache when the "cache" option is "true" and the asset has been changed: assets 1`] = ` { "foo.css": "body{color:red}a{color:blue} @@ -396,6 +406,16 @@ exports[`CssMinimizerPlugin should work with warnings and use memory cache when ] `; +exports[`CssMinimizerPlugin should work: assets 1`] = ` +{ + "main.css": "body{color:red}a{color:blue}", +} +`; + +exports[`CssMinimizerPlugin should work: errors 1`] = `[]`; + +exports[`CssMinimizerPlugin should work: warnings 1`] = `[]`; + exports[`CssMinimizerPlugin should write stdout and stderr of workers to stdout and stderr of main process in parallel mode: assets 1`] = ` { "one.css": ".minify {};", diff --git a/test/__snapshots__/minify-option.test.js.snap b/test/__snapshots__/minify-option.test.js.snap index 59cca25..54a437e 100644 --- a/test/__snapshots__/minify-option.test.js.snap +++ b/test/__snapshots__/minify-option.test.js.snap @@ -510,15 +510,7 @@ exports[`"minify" option should work with "csso" minifier: warning 1`] = `[]`; exports[`"minify" option should work with empty code: assets 1`] = ` { - "foo.css": "body { - color: red; -} -a { - color: blue; -} - -/*# sourceMappingURL=foo.css.map*/", - "foo.css.map": "{"version":3,"file":"foo.css","mappings":"AAAA;EACE,UAAU;AACZ;AACA;EACE,WAAW;AACb,C","sources":["webpack:///./foo.css"],"sourcesContent":["body {\\n color: red;\\n}\\na {\\n color: blue;\\n}"],"names":[],"sourceRoot":""}", + "foo.css": "", } `; diff --git a/test/fixtures/empty.css b/test/fixtures/empty.css new file mode 100644 index 0000000..3e6ea4a --- /dev/null +++ b/test/fixtures/empty.css @@ -0,0 +1 @@ +/* comment */ diff --git a/test/fixtures/empty.js b/test/fixtures/empty.js new file mode 100644 index 0000000..64fbfa7 --- /dev/null +++ b/test/fixtures/empty.js @@ -0,0 +1 @@ +import "./empty.css"; diff --git a/test/helpers/getCompiler.js b/test/helpers/getCompiler.js index 3e4d07b..24a940b 100644 --- a/test/helpers/getCompiler.js +++ b/test/helpers/getCompiler.js @@ -8,7 +8,7 @@ import webpack from "webpack"; * @param {import("webpack").Configuration} config Webpack configuration * @returns {import("webpack").Compiler} Webpack compiler */ -export default function getCompiler(config) { +export default function getCompiler(config = {}) { const compiler = webpack({ mode: "development", devtool: config.devtool || false, From 86ee07da1ba7d856a1942dd1a283bab0df29b21b Mon Sep 17 00:00:00 2001 From: alexander-akait Date: Thu, 11 Dec 2025 23:39:46 +0300 Subject: [PATCH 2/2] chore(release): 7.0.4 --- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 011f985..84815c4 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. +### [7.0.4](https://github.com/webpack/css-minimizer-webpack-plugin/compare/v7.0.3...v7.0.4) (2025-12-11) + + +### Bug Fixes + +* handle empty files ([#295](https://github.com/webpack/css-minimizer-webpack-plugin/issues/295)) ([8b273d1](https://github.com/webpack/css-minimizer-webpack-plugin/commit/8b273d15f9ca2baf7cd0e3c03817e74be7221e5b)) + ### [7.0.3](https://github.com/webpack/css-minimizer-webpack-plugin/compare/v7.0.2...v7.0.3) (2025-12-05) diff --git a/package-lock.json b/package-lock.json index dadee2d..fc97913 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "css-minimizer-webpack-plugin", - "version": "7.0.3", + "version": "7.0.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "css-minimizer-webpack-plugin", - "version": "7.0.3", + "version": "7.0.4", "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", diff --git a/package.json b/package.json index 3da9b64..71bc430 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "css-minimizer-webpack-plugin", - "version": "7.0.3", + "version": "7.0.4", "description": "CSS minimizer (minifier) plugin for Webpack", "keywords": [ "cssnano",