From c8534075fc8307acd383b352bc47fc1260028c3f Mon Sep 17 00:00:00 2001 From: alexander-akait Date: Sun, 6 Sep 2026 12:31:04 +0000 Subject: [PATCH] feat: let a minimizer in `minify` state its own `filter` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A minimizer said which assets it wanted through a `filter` property on the function, so two entries of the same minimizer could not each have one — the pattern `image-minimizer-webpack-plugin` wrote as `minimizer: [{ implementation, options, filter }, …]`. A descriptor's `filter` answers for that entry and falls back to the function's own. Documents, with it, what `minify` cannot reach: an image that becomes a `data:` URI is never an emitted asset, so a raster inline is minified by `generate` — which runs over the module's bytes — rather than here. Only a language written as text is offered as embedded source, which is why an inline SVG is the exception. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_016TQeNpahUSDUjD2Crugy5H --- .changeset/060-minify-filter.md | 5 + README.md | 69 +++++++++- src/index.js | 20 +-- src/options.json | 8 ++ src/utils.js | 12 +- .../validate-options.test.js.snap | 6 +- test/minify-option.test.js | 119 ++++++++++++++++++ types/index.d.ts | 3 + types/utils.d.ts | 7 +- 9 files changed, 234 insertions(+), 15 deletions(-) create mode 100644 .changeset/060-minify-filter.md diff --git a/.changeset/060-minify-filter.md b/.changeset/060-minify-filter.md new file mode 100644 index 0000000..96786f0 --- /dev/null +++ b/.changeset/060-minify-filter.md @@ -0,0 +1,5 @@ +--- +"minimizer-webpack-plugin": minor +--- + +Allow a minimizer in `minify` to state its own `filter`. diff --git a/README.md b/README.md index 7c30a9b..98042d8 100644 --- a/README.md +++ b/README.md @@ -370,6 +370,22 @@ default one, and the tables in [webpack's own minimizers](#webpacks-own-minimizers) for `cssMinify` and `htmlMinify`. +`filter(name, info)` states which assets this minimizer is offered — return +`false` to decline one, and anything else (`undefined` included) to accept. It +answers for a `filter` property on the minimizer function itself, which is what +the built-ins carry, so setting it here is how you narrow one of them without +wrapping it. + +```js +new MinimizerPlugin({ + minify: { + implementation: MinimizerPlugin.sharpMinify, + options: { encodeOptions: { jpeg: { quality: 80 } } }, + filter: (name) => !name.includes("do-not-touch"), + }, +}); +``` + Two keys are filled in before a minimizer sees them, and only when `options` does not set them itself: `ecma`, from [`output.environment`](https://webpack.js.org/configuration/output/#outputenvironment), @@ -441,7 +457,28 @@ module.exports = { }; ``` -This is what lets **one plugin instance and one worker pool** handle every +Each entry carries its own `filter` as well as its own `options`, which is how +the same minimizer runs twice over different assets: + +```js +new MinimizerPlugin({ + test: /\.(jpe?g|png)$/i, + minify: [ + { + implementation: MinimizerPlugin.sharpMinify, + options: { encodeOptions: { jpeg: { quality: 60 } } }, + filter: (name) => name.includes("thumb"), + }, + { + implementation: MinimizerPlugin.sharpMinify, + options: { encodeOptions: { jpeg: { quality: 90 } } }, + filter: (name) => !name.includes("thumb"), + }, + ], +}); +``` + +This is also what lets **one plugin instance and one worker pool** handle every asset type: each built-in ships with a `filter` matching its natural extension, so JS, CSS, HTML and JSON need no second instance. `test` still defaults to JS only, so widen it to let the other assets reach the dispatcher: @@ -1177,7 +1214,9 @@ What this reaches: `exportType` but `link`). - The text an `asset/source` module embeds, and the payload an `asset/inline` module encodes — the payload before it is encoded, so the encoding covers - what came back. + what came back. **A language written as text only**: an inline `svg` is + offered, an inline `png` or `jpeg` is not, so a raster image that becomes a + `data:` URI is minified by [`generate`](#generate) rather than here. - What a document or a stylesheet nests inside itself: an inline `