Repository navigation
feat(minify): add and drop CSS vendor prefixes for the browserslist target - #21602
aryanraj45 wants to merge 5 commits into
Conversation
🦋 Changeset detectedLatest commit: 2318c90 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
e31719f to
5b82e0b
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #21602 +/- ##
==========================================
+ Coverage 94.21% 94.22% +0.01%
==========================================
Files 628 628
Lines 78998 79268 +270
Branches 23304 23405 +101
==========================================
+ Hits 74425 74692 +267
- Misses 4573 4576 +3
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Merging this PR will regress 1 benchmark
|
| Mode | Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|---|
| ❌ | Memory | benchmark "many-modules-interop-runtime", scenario '{"name":"mode-production","mode":"production"}', measure 'exec' |
18.9 KB | 25.3 KB | -25.36% |
| ⚡ | Memory | benchmark "react", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' |
809.2 KB | 240.9 KB | ×3.4 |
| ⚡ | Memory | benchmark "three-long", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' |
1,158.2 KB | 706.1 KB | +64.04% |
| ⚡ | Memory | benchmark "css-modules", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' |
923.3 KB | 751.6 KB | +22.86% |
Tip
Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.
Comparing aryanraj45:feat/css-vendor-prefixes (1496047) with main (9d3b707)
5b82e0b to
1496047
Compare
|
@alexander-akait rebased into main can u please re-run the ci again thanks :)) |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 1496047. Configure here.
…list target Generate a prefix table from @mdn/browser-compat-data at build time and, when the default minimizer runs for a browserslist target, add the -webkit-/-moz-/-ms- spellings the selected browsers still need and drop the ones none do. Covers properties, at-rules and pseudo-selectors; sibling awareness for at-rules and selectors uses a small running set of top-level rules, not a whole-stylesheet buffer, so the streaming printer's peak-heap stays flat.
…ensitively Two prefixing bugs: a later at-rule or pseudo-selector with the same signature as an earlier one no longer skips its prefixed copy, so a rule that overrides an earlier keeps its prefixed twin winning too; and a pseudo name is lowercased before the table lookup, so an ASCII case variant like ::PLACEHOLDER is prefixed like the lowercase spelling, as property and at-rule names already are.
An at-rule name is case-insensitive, so a cased `@Keyframes` and a prefixed `@-webkit-keyframes` must share one signature. The unprefixed branch keyed the raw prelude, which kept the author's case, so the two never paired — a prefixed copy was duplicated or a dead one left in. Key both off the lowercased `@base` spelling.
…eudos Two edge cases: the sibling set that tracks at-rules and selectors has no nesting key, so restrict rule-level prefixing to top-level rules — a nested `@keyframes` or pseudo no longer adds or drops against a same-named top-level rule in another scope (a nested rule's declarations are still prefixed). And a functional pseudo like `:dir(rtl)` prints as one token, so match and rewrite its name apart from the argument, which is kept in the sibling signature so `:dir(rtl)` and `:dir(ltr)` stay distinct.
1496047 to
1bb4658
Compare
|
Note
|
| Layer / File(s) | Summary |
|---|---|
Browser target resolution lib/config/target.js, lib/config/defaults.js |
Browserslist targets are parsed, loaded, deduplicated, and passed to minimizer environments. |
Prefix compatibility data tooling/generate-css-data.js, package.json |
MDN compatibility data generates prefix tables for properties, selectors, and at-rules. |
CSS prefix processing lib/css/syntax.js |
The CSS printer removes unnecessary prefixes and generates required prefixed declarations, rules, and selectors. |
Validation and release support test/CssSyntax.unittest.js, test/configCases/css/minimize-vendor-prefixes/*, .changeset/158-css-vendor-prefixes.md, cspell.json |
Tests cover target-driven prefix handling. The configuration fixture and release metadata describe the behavior. |
Possibly related PRs
- webpack/webpack#21663: Updates the shared CSS/HTML minimizer environment and options pipeline.
Suggested reviewers: alexander-akait, bjohansebas
🚥 Pre-merge checks | ✅ 3 | ❌ 1
❌ Failed checks (1 inconclusive)
| Check name | Status | Explanation | Resolution |
|---|---|---|---|
| Title check | ❓ Inconclusive | The title follows the conventional-commit format and accurately describes the CSS vendor-prefix change, but the branch prefix is not provided for verification. | Provide the branch name or branch prefix so the required type-prefix match can be verified. |
✅ Passed checks (3 passed)
| Check name | Status | Explanation |
|---|---|---|
| Description Check | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled. |
| Linked Issues check | ✅ Passed | Check skipped because no linked issues were found for this pull request. |
| Out of Scope Changes check | ✅ Passed | Check skipped because no linked issues were found for this pull request. |
Comment @coderabbitai help to get the list of available commands.
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (8)
test/CssSyntax.unittest.js (2)
4316-4320: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueHoist the triplicated
minifyhelper.The three new
describeblocks each define a byte-identical helper. Define it once above them and share it.Also applies to: 4436-4440, 4518-4522
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/CssSyntax.unittest.js` around lines 4316 - 4320, Hoist the identical minify helper from the three describe blocks into a single shared definition above them in the test module. Remove each local duplicate and have all three blocks reuse the shared minify function, preserving its existing SourceProcessor configuration and return behavior.
4462-4468: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winNo test covers the prefixed-first rule order, which is the order authors write.
Both rule-level removal tests place the unprefixed rule first.
_prefixAtRuleand_prefixQualifiedRuleremove a prefixed rule only whenseen.has(signature)already holds (lines 5980 and 6094), so removal depends on the unprefixed twin being printed first. The streaming printer cannot look ahead, and the comment at line 5959 states this constraint.Prefix fallbacks are conventionally authored prefixed-first, so the untested order is the common input, and in it no removal happens. Declarations are unaffected:
presentis built from all declarations before the loop at lines 9225-9229, so declaration removal is order-independent.Add a case that pins the prefixed-first behavior. That documents the limitation and catches a future change to it.
💚 Pin the documented order dependency
+ it("keeps a prefixed at-rule written before its unprefixed twin — streaming cannot look ahead", () => { + expect( + minify("`@-webkit-keyframes` s{to{opacity:1}}`@keyframes` s{to{opacity:1}}", [ + "chrome 120" + ]) + ).toBe("`@-webkit-keyframes` s{to{opacity:1}}`@keyframes` s{to{opacity:1}}"); + });As per path instructions: "Cover every changed line and branch with tests, preferably through integration cases."
Also applies to: 4548-4554
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/CssSyntax.unittest.js` around lines 4462 - 4468, Add test coverage for prefixed-first ordering in the rule-level at-rule removal tests near the existing prefixed/unprefixed cases: place the prefixed `@-webkit-keyframes` rule before its unprefixed `@keyframes` twin and assert the current streaming behavior, preserving the documented order dependency. Apply the same coverage to the corresponding test around the alternate referenced range, without changing implementation behavior.Source: Path instructions
tooling/generate-css-data.js (4)
3570-3587: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winThe comment claims a standard-status filter that
collectPrefixTabledoes not implement.The comment states "Standard entries only — a construct BCD marks non-standard is a vendor's own, not a spelling of a standard one." No code reads a status field.
collectPrefixTableskips only names starting with__, andcollectPrefixesfilters by prefix spelling and engine, never by standard status.The behavior differs from the claim. A construct BCD lists with prefix-only support and no unprefixed entry gets
unprefixedFrom === null, sotargetbecomesInfinityat line 3528 and the entry is emitted with an always-needed window. The minifier then adds a prefixed copy beside any authored occurrence of that base name.Either read the BCD status and skip non-standard entries, or correct the comment to describe the actual filter.
As per coding guidelines: "comments must add non-obvious information and must not narrate or restate code."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tooling/generate-css-data.js` around lines 3570 - 3587, Update the comment above collectPrefixTable to accurately describe its actual behavior: it excludes internal names beginning with "__" and includes entries for which collectPrefixes returns data, without claiming a standard-status filter. Keep the implementation unchanged unless needed to make the revised comment precise.Source: Coding guidelines
3444-3446: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueTrim the new comment blocks to two lines.
Four of the new comment blocks run three to five lines: 3444-3446, 3463-3467, 3484-3487, and 3503-3507. Each states useful non-obvious reasoning, so the content should stay — move the detail into the adjacent JSDoc block, which has no length limit, and keep the leading comment to two lines.
As per coding guidelines: "Keep comments as short as possible, generally one line and no more than two short lines."
Also applies to: 3463-3467, 3484-3487, 3503-3507
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tooling/generate-css-data.js` around lines 3444 - 3446, Shorten the new leading comment blocks near the BCD browser-id mapping and the corresponding blocks at the other referenced locations to no more than two lines. Preserve their non-obvious reasoning by moving the excess detail into each adjacent JSDoc block.Source: Coding guidelines
2534-2547: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse
JSON.stringifyfor the interpolated names, matching the other literal helpers.
prefixLiteralinterpolatesname,prefix, andbrowserdirectly into"…"with no escaping. Every other literal helper in this file goes throughJSON.stringifyfor the same job — see thePOSITION_X_KEYWORDSemission at line 3848 and theFAMILY_LONGHANDSemission at line 3727.The values are CSS identifiers today, so no quote or backslash reaches the output. The inconsistency is what makes this worth changing: a future BCD key with an unexpected character would emit broken JavaScript into
lib/css/data.jsrather than failing in the generator.♻️ Match the file's escaping convention
const prefixLiteral = (table) => `new Map([${table .map(([name, prefixes]) => { const body = prefixes .map(([prefix, browsers]) => { const list = browsers - .map(([browser, from, to]) => `["${browser}", ${from}, ${to}]`) + .map( + ([browser, from, to]) => + `[${JSON.stringify(browser)}, ${from}, ${to}]` + ) .join(", "); - return `["${prefix}", [${list}]]`; + return `[${JSON.stringify(prefix)}, [${list}]]`; }) .join(", "); - return `["${name}", [${body}]]`; + return `[${JSON.stringify(name)}, [${body}]]`; }) .join(", ")}])`;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tooling/generate-css-data.js` around lines 2534 - 2547, Update the prefixLiteral helper so the interpolated name, prefix, and browser values are serialized with JSON.stringify instead of manual double-quoted interpolation. Match the escaping convention used by the other literal helpers while preserving the generated Map structure and numeric from/to values.
3463-3482: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoffDerive the engine-to-prefix mapping from BCD's release
enginefield.
BROWSER_PREFIXEShand-types 13 browser entries. BCD publishes the engine for every release atbcd.browsers[id].releases[version].engine— "Blink", "Gecko", "WebKit", "Presto", "EdgeHTML", "Trident". A table of 6 engines to prefixes, joined against that field, replaces the 13 browser rows and covers the dual listings foredgeandoperafrom the data instead of from the comment.
BCD_TO_BROWSERSLISTat lines 3447-3461 is a different case. No published dataset links BCD ids to browserslist names, and the comment states why BCD-only engines are absent, so the hand-typed map is justified there.As per path instructions: "Generators must derive tables from published datasets (mdn-data, color-name, vendored webref) rather than hand-typing name lists; a SUPPLEMENT entry needs a stated reason it cannot be derived."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tooling/generate-css-data.js` around lines 3463 - 3482, Replace the hand-typed browser entries in BROWSER_PREFIXES with a six-engine-to-prefix mapping derived from BCD release metadata. Build the browser prefix lookup by joining each bcd.browsers[id].releases[version].engine value to the corresponding engine prefixes, preserving the published engine-specific prefixes and allowing EdgeHTML/Trident and Presto cases to emerge from the data. Leave BCD_TO_BROWSERSLIST unchanged.Source: Path instructions
lib/css/syntax.js (1)
5948-5954: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
_neededPrefixesreturnsnullfor two opposite meanings, and_prefixRemovablereads the wrong one as removable.
_neededPrefixesreturnsnullwhen no target needs a prefix (line 5927) and also whenbrowsersis absent (line 5893). At line 5953_prefixRemovabletreatsnullas removable. So a caller reaching_prefixRemovablewithout a browser list would strip author prefixes with no target information — silently wrong output CSS.Every current caller is gated. The declaration path checks
environment.browsersat lines 9218-9222. The rule paths run only when_seenPrefixRules !== null, which requires the same check at lines 4665-4671. So this is not reachable today.The overload is what makes it fragile: the gate lives in the callers, not in the function that depends on it. An explicit check inside
_prefixRemovablemakes the requirement local.♻️ Make the precondition local
const _prefixRemovable = (table, base, prefix, tag, writer) => { + const environment = /** `@type` {CssEnvironment | undefined} */ ( + writer.options.environment + ); + // No target list means no basis to judge a prefix dead; keep it. + if (!environment || !environment.browsers) return false; const prefixes = table.get(base); if (prefixes === undefined) return false;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@lib/css/syntax.js` around lines 5948 - 5954, Update _prefixRemovable to explicitly require an available browser list before treating a prefix as removable; when the required browser information is absent, return false. Preserve the existing _neededPrefixes handling for cases where browser data exists, including removing prefixes only when its result confirms the prefix is unnecessary.test/configCases/css/minimize-vendor-prefixes/webpack.config.js (1)
5-8: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winShorten the configuration comment to two lines.
The comment spans four lines. Keep the non-obvious reason for the Browserslist target and stable versions.
Suggested revision
- // A browserslist target so the default minimizer wiring resolves its browser - // list and hands it to `cssMinify` — the whole option flow, not the - // serializer alone. Exact versions in `.browserslistrc` keep the snapshot - // stable as caniuse updates. + // A browserslist target lets the default minimizer resolve browser targets. + // Exact versions keep the snapshot stable as caniuse updates.As per coding guidelines, comments under
{lib,hot,tooling,test}/**/*.{js,mjs}must be as short as possible and no more than two short lines. As per path instructions, comments undertest/**follow the same limit.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/configCases/css/minimize-vendor-prefixes/webpack.config.js` around lines 5 - 8, Shorten the comment above the Browserslist target to no more than two short lines while preserving both points: the target exercises the default minimizer-to-cssMinify option flow, and exact versions keep snapshots stable as caniuse updates.Sources: Coding guidelines, Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.changeset/158-css-vendor-prefixes.md:
- Line 5: Shorten the changeset summary to one capitalized imperative sentence
of 80 characters or fewer, preserving that CSS vendor prefixes are added or
removed based on the browserslist target.
In `@lib/config/defaults.js`:
- Around line 2479-2492: Update the browser resolution in the minimizerOptions
path around the browsers variable so worker tasks reuse a stable per-worker
browser list instead of creating a new array for each asset. Preserve the
existing target normalization and Context handling, and ensure the css/syntax
WeakMap caches can retain entries across assets by resolving the list once or
replacing identity-based caching with an equivalent value-based key.
In `@lib/css/syntax.js`:
- Around line 4665-4671: The finally cleanup in grammar() must also release
_seenPrefixRules after each parse. Add it to the existing per-parse module-state
reset alongside the other fields, preserving the current initialization and
minification behavior during parsing.
- Around line 9230-9269: Update the prefix-handling loop to use the property
name emitted by replacement text for merged longhand indices, or skip prefix
processing for those indices. Ensure merged border-radius entries still receive
the required -moz-border-radius prefix while preserving normal handling for
unmerged declarations.
In `@test/CssSyntax.unittest.js`:
- Around line 4409-4413: Rename the test case describing Safari Technology
Preview so it no longer claims “no prefix” and instead reflects that the TP rule
adds the expected -webkit-user-select prefix. Keep the assertion and test
behavior unchanged.
In `@tooling/generate-css-data.js`:
- Around line 3522-3527: Update the unprefixed-version calculation in the
entries loop to select the earliest non-prefixed version independent of BCD
array order, and account for each entry’s version_removed so unprefixed support
applies only within its active version range. Preserve separate unprefixed
windows for re-added entries rather than allowing a later entry to overwrite
earlier boundaries.
---
Nitpick comments:
In `@lib/css/syntax.js`:
- Around line 5948-5954: Update _prefixRemovable to explicitly require an
available browser list before treating a prefix as removable; when the required
browser information is absent, return false. Preserve the existing
_neededPrefixes handling for cases where browser data exists, including removing
prefixes only when its result confirms the prefix is unnecessary.
In `@test/configCases/css/minimize-vendor-prefixes/webpack.config.js`:
- Around line 5-8: Shorten the comment above the Browserslist target to no more
than two short lines while preserving both points: the target exercises the
default minimizer-to-cssMinify option flow, and exact versions keep snapshots
stable as caniuse updates.
In `@test/CssSyntax.unittest.js`:
- Around line 4316-4320: Hoist the identical minify helper from the three
describe blocks into a single shared definition above them in the test module.
Remove each local duplicate and have all three blocks reuse the shared minify
function, preserving its existing SourceProcessor configuration and return
behavior.
- Around line 4462-4468: Add test coverage for prefixed-first ordering in the
rule-level at-rule removal tests near the existing prefixed/unprefixed cases:
place the prefixed `@-webkit-keyframes` rule before its unprefixed `@keyframes` twin
and assert the current streaming behavior, preserving the documented order
dependency. Apply the same coverage to the corresponding test around the
alternate referenced range, without changing implementation behavior.
In `@tooling/generate-css-data.js`:
- Around line 3570-3587: Update the comment above collectPrefixTable to
accurately describe its actual behavior: it excludes internal names beginning
with "__" and includes entries for which collectPrefixes returns data, without
claiming a standard-status filter. Keep the implementation unchanged unless
needed to make the revised comment precise.
- Around line 3444-3446: Shorten the new leading comment blocks near the BCD
browser-id mapping and the corresponding blocks at the other referenced
locations to no more than two lines. Preserve their non-obvious reasoning by
moving the excess detail into each adjacent JSDoc block.
- Around line 2534-2547: Update the prefixLiteral helper so the interpolated
name, prefix, and browser values are serialized with JSON.stringify instead of
manual double-quoted interpolation. Match the escaping convention used by the
other literal helpers while preserving the generated Map structure and numeric
from/to values.
- Around line 3463-3482: Replace the hand-typed browser entries in
BROWSER_PREFIXES with a six-engine-to-prefix mapping derived from BCD release
metadata. Build the browser prefix lookup by joining each
bcd.browsers[id].releases[version].engine value to the corresponding engine
prefixes, preserving the published engine-specific prefixes and allowing
EdgeHTML/Trident and Presto cases to emerge from the data. Leave
BCD_TO_BROWSERSLIST unchanged.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 4c667df1-e440-4043-9c51-da693a0f0ba3
⛔ Files ignored due to path filters (5)
lib/css/data.jsis excluded by!lib/css/data.jstest/configCases/css/minimize-vendor-prefixes/__snapshots__/ConfigCacheTest.snapis excluded by!**/*.snap,!test/**/__snapshots__/**test/configCases/css/minimize-vendor-prefixes/__snapshots__/ConfigTest.snapis excluded by!**/*.snap,!test/**/__snapshots__/**types.d.tsis excluded by!types.d.tsyarn.lockis excluded by!**/yarn.lock,!**/*.lock,!yarn.lock
📒 Files selected for processing (13)
.changeset/158-css-vendor-prefixes.mdcspell.jsonlib/config/defaults.jslib/config/target.jslib/css/syntax.jspackage.jsontest/CssSyntax.unittest.jstest/configCases/css/minimize-vendor-prefixes/.browserslistrctest/configCases/css/minimize-vendor-prefixes/index.jstest/configCases/css/minimize-vendor-prefixes/style.csstest/configCases/css/minimize-vendor-prefixes/test.config.jstest/configCases/css/minimize-vendor-prefixes/webpack.config.jstooling/generate-css-data.js
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
webpack/schema-utils(auto-detected)webpack/tapable(auto-detected)
…BCD's earliest unprefixed version A merged box shorthand is stored on one longhand's node, so the node name is not the property emitted — border-radius went unprefixed for a target needing -moz-. In the generator, the unprefixed arrival is the earliest support entry rather than the last read, and one BCD later removed never established it. Also release the prefix-rule set with the other per-parse state, and key the browserslist memo on the joined text so a worker's fresh array still hits it.
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
lib/css/syntax.js (1)
9251-9292: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy liftTrack complete declarations, not property names.
Lines 9251-9292 treat one existing prefixed property as coverage for every declaration of that property. For
-webkit-appearance:auto;appearance:none, a target that requires-webkit-does not receive-webkit-appearance:nonebecause Line 9289 sees-webkit-appearanceas present. That target appliesautoinstead ofnone.The same property-only check can remove an authored prefixed declaration with distinct value or cascade behavior. Track normalized declaration text, including value and
!important, and preserve declaration order when adding or removing prefixes.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@lib/css/syntax.js` around lines 9251 - 9292, Update the declaration tracking and prefix-removal/addition logic around _printedProperty so coverage is based on normalized complete declaration text, including value and !important, rather than property names alone. Ensure -webkit-appearance:auto and appearance:none are handled independently, and preserve authored declaration order when inserting required prefixes or removing redundant ones.
🧹 Nitpick comments (1)
tooling/generate-css-data.js (1)
3524-3526: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winShorten the new comments. Both comments use three lines and repeat behavior expressed by the adjacent code. Keep only the non-obvious reason in no more than two short lines.
tooling/generate-css-data.js#L3524-L3526: reduce the BCD ordering explanation to one or two short lines.lib/css/syntax.js#L5832-L5834: reduce the memo-key explanation to one or two short lines.As per coding guidelines: "Keep comments as short as possible, generally one line and no more than two short lines; comments must add non-obvious information and must not narrate or restate code."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tooling/generate-css-data.js` around lines 3524 - 3526, Shorten the comments at tooling/generate-css-data.js lines 3524-3526 and lib/css/syntax.js lines 5832-5834 to one or two short lines each, retaining only the non-obvious BCD ordering and memo-key rationale; remove wording that repeats adjacent code behavior.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@lib/css/syntax.js`:
- Around line 9251-9292: Update the declaration tracking and
prefix-removal/addition logic around _printedProperty so coverage is based on
normalized complete declaration text, including value and !important, rather
than property names alone. Ensure -webkit-appearance:auto and appearance:none
are handled independently, and preserve authored declaration order when
inserting required prefixes or removing redundant ones.
---
Nitpick comments:
In `@tooling/generate-css-data.js`:
- Around line 3524-3526: Shorten the comments at tooling/generate-css-data.js
lines 3524-3526 and lib/css/syntax.js lines 5832-5834 to one or two short lines
each, retaining only the non-obvious BCD ordering and memo-key rationale; remove
wording that repeats adjacent code behavior.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 7406e1a9-faeb-4a66-9131-cc4a5169130b
⛔ Files ignored due to path filters (1)
lib/css/data.jsis excluded by!lib/css/data.js
📒 Files selected for processing (4)
.changeset/158-css-vendor-prefixes.mdlib/css/syntax.jstest/CssSyntax.unittest.jstooling/generate-css-data.js
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
webpack/schema-utils(auto-detected)webpack/tapable(auto-detected)
🚧 Files skipped from review as they are similar to previous changes (2)
- .changeset/158-css-vendor-prefixes.md
- test/CssSyntax.unittest.js
|
@alexander-akait Rebased on main. Also fixed the review comments - the border-radius one was a real bug, the merged shorthand never got Can u please take a look and re-run the CI, thanks! |
|
Fixed with a lot of fixes in the main, thanks for start and helping me |

Summary
Native CSS minification now maintains vendor prefixes for the
browserslisttarget: when the default minimizer runs, it adds the-webkit-/-moz-/-ms-spellings the selected browsers still need and drops the ones none of them do. It covers all three axes a prefix appears on:user-select: none→-webkit-user-select/-moz-user-selectadded for old targets; a dead-webkit-border-radiusdropped for modern ones@keyframesgains a@-webkit-keyframescopy when needed::placeholder→::-webkit-input-placeholder, keeping the author's colonsThe prefix table is generated from
@mdn/browser-compat-dataat build time intolib/css/data.js(like every other CSS lookup table), sosyntax.jsstays algorithm-only and a data-package bump lands as a reviewable diff. Each browser is filtered to its own engine's prefix, so obsolete cross-engine ones (e.g.-khtml-) are never emitted. At-rule and selector siblings are tracked with a small running set of top-level rules as the printer streams — no whole-stylesheet buffer, so peak heap stays flat.Scope note: this is the prefixes half of the two-part plan. Modern↔legacy value-syntax rewriting (e.g. gradient direction) is a separate follow-up, since prefixing those requires argument transforms rather than a prefix.
What kind of change does this PR introduce?
feat
Did you add tests for your changes?
Yes.
test/CssSyntax.unittest.jsadds 28 unit cases across the three axes (add, remove, no-double, minor-version boundaries, version ranges, Safari TP, selector-list skip, off-without-target), andtest/configCases/css/minimize-vendor-prefixesdrives a realbrowserslistbuild exercising all three axes end to end.Does this PR introduce a breaking change?
No.
If relevant, what needs to be documented once your changes are merged or what have you already documented?
The CSS minifier now adds/removes vendor prefixes automatically based on the resolved
browserslisttarget; there is no new configuration option.Use of AI
Yes
Note
Medium Risk
Changes emitted CSS for production builds with browserslist targets and large generated compat tables; incorrect prefix logic could break styles in older browsers, though behavior is gated on
environment.browsersand covered by unit and config-case tests.Overview
CSS minification now adds and removes vendor prefixes based on the resolved browserslist target when the default minimizer runs—no new user option.
Wiring:
getTargetsBrowsers()merges browsers frombrowserslisttargets; the default minimizer passes that list asenvironment.browsersinto CSS and HTML minify (inline styles stay aligned).Data:
tooling/generate-css-data.jsbuildsPREFIXED_PROPERTIES,PREFIXED_SELECTORS, andPREFIXED_AT_RULESfrom @mdn/browser-compat-data intolib/css/data.js. Prefix need is decided per browser version window; only each engine’s own prefixes are considered (obsolete cross-engine spellings like-khtml-are not emitted).Minify behavior in
lib/css/syntax.jswhenenvironment.browsersis set:@keyframes): prepend needed prefixed copies; drop prefixed rules superseded by an unprefixed sibling.::placeholder): same add/drop pattern; comma-separated selector lists are left unchanged.Without a browserslist-backed browser list, prefix handling is unchanged. Types document optional
CssEnvironment.browsers.Reviewed by Cursor Bugbot for commit 1496047. Bugbot is set up for automated code reviews on this repo. Configure here.
Summary by CodeRabbit
New Features
user-select,appearance, placeholders, and related CSS features.Bug Fixes