All notable changes to CSS Dedup are documented in this file, which is (mostly) AI-generated and (always) human-edited. Dependency updates may or may not be called out specifically.
The format is based on Keep a Changelog, and the project adheres to Semantic Versioning.
- Added
CSS_DEDUP_WORKERSto override the thread count for a run (0or1processes files one at a time)
- Sped up multi-file runs by spreading consolidation across worker threads (one per core, minus one for the main thread); output is byte-identical to a single-threaded run, since every file is still rendered from the main thread in file order, and runs too small to pay for a pool stay on one thread
- Adjusted source map warning to no longer fire for a
sourceMappingURLstring that merely appears in a declaration value (content: "/*# sourceMappingURL=… */"), since detection now inspects parsed comments rather than the raw style sheet text
- Updated
dedup()to returnsourceMapStale: truewhen it rewrites a style sheet carrying asourceMappingURLcomment, so programmatic users get the caveat the CLI already printed
- Reworded the source map warning: The map should be treated as invalid rather than stale-but-usable (especially for minified style sheets, where every mapping is keyed by column), and both it and the README now point at running CSS Dedup before the minifier, or in-pipeline via
css-dedup/plugin, to keep maps intact
- Renamed the aggressive-mode preview bullet’s count from “findings” to “declarations,” to make wording correct and consistent
- Added
npm run benchmarkto time both entry points against a generated style sheet (or files/directories passed as arguments), reporting declarations applied, groups skipped, and bytes saved alongside each timing
- Sped up consolidation by roughly 3–5× on large style sheets, by bounding the merge-safety scan to the span it actually examines and memoizing property normalization, selector splitting, and shorthand/longhand overlap per run
- Added
--quiet/-qto suppress the per-file findings/skipped-group detail listing (and its file-path header); summaries still print
- Tweaked some messages (and comments)
- A missing target path, or a directory
readdircan’t access, now reports a clean error instead of a raw stack trace
- Added
--exit-zero/-z(and theexitZeroconfig option) to exit “0” even when findings are skipped as unsafe to auto-merge or withheld by--savings-only, so a build pipeline doesn’t gate on them- A file that fails to read or parse still exits “1” regardless of the flag.
- Added
--no-exit-zero/-eto overrideexitZero: truefrom a config file for a run
- Corrected
--aggressiveto require--fix(similar to--savings-only)
- Optimized report mode’s bulleted summary with a compact table (
Summary for <file>:) comparing all four--fix/--savings-only/--aggressivecombinations at once
- Optimized summaries further, especially for aggressive mode
- Added an overall summary (
Summary for all files: …) at the end of a multi-file run
- Optimized individual summaries
--fixno longer de-minifies an already-minified style sheet: A merged selector list now follows the source’s comma-spacing convention (.a,.bvs..a, .b) instead of inserting a space
- Fixed a merged rule inserted directly after a comment-adjacent (or otherwise tightly-spaced) source rule inheriting that rule’s spacing
- Tightened README and CLI info wording
- A single-dash spelling of a long option name (e.g.,
-fixfor--fix) is now rejected with a suggestion, instead of silently parsing as a cluster of short flags (-fplus-iwith an unintended attached value)
- Added license (MIT)
- Added
--ignore-path/-p(ignorePathsin the config file) to exclude files by path—matched against each file’s path relative to the working directory --fixnow warns when it rewrites a file that references a source map (sourceMappingURL), since the map itself isn’t regenerated and goes stale- Duplicate detection now canonicalizes
<time>values (s/ms) unconditionally - Duplicate detection now sorts
min()/max()arguments, since mathematical min/max is commutative - Aggressive mode: Duplicate detection now canonicalizes
<angle>values (deg/grad/rad/turn)
- File reads are now prefetched concurrently ahead of the (still sequential and deterministically ordered) per-file processing loop, overlapping I/O latency across a multi-file run
--fixnow prints the skipped-group detail before the consolidated/withheld/skipped counts summary, so the summary isn’t stranded above a long skipped-group list
- Added TypeScript declaration files (
src/index.d.ts,src/plugin.d.ts) for the programmatic API and the PostCSS plugin
- Added aggressive mode (
--aggressive/-aon the CLI,aggressive: trueprogrammatically and in the config file) for merges that are probably—but not provably—safe- Without the flag, reports and
--fixruns now note in parentheses what--aggressivewould additionally consolidate; after an aggressive--fix, the CLI counts the merges that rode on the flag and suggests reviewing and testing
- Without the flag, reports and
- Added
--savings-only/-sparameter (savingsOnly: trueprogrammatically, in the plugin, and in the config file) that complements--fix/-f, leaving files whose consolidation would make it bigger untouched—checked per file, so a multi-file run still writes the files that shrink; a withheld result is reported (CLI) or warned about (plugin), anddedup()returns it underwithheld
- Released initial version