[CLOV-1637] Phase 2: add postcss mangle to shortcut names#4633
Open
IrinaWei wants to merge 1 commit into
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Stacked on top of #4630. Applies the third (and final) of three planned compression strategies for
base.css, taking the bundle from ~9.77 KB → ~7.92 KB on top of the savings already landed in #4630.Combined with the previous PR,
base.cssshrinks from ~15.5 KB (after the token block in #4492) to ~7.92 KB — about a 48.9% total reduction.📦42.19.1-dev-v26387757985.1

Strategy 3: Mangle CSS custom property names via a PostCSS plugin
Backpack's CSS custom properties carry full semantic names (
--bpk-private-button-colour-bg-primary,--bpk-typography-style-headline, …). Those names are great for authoring and debugging, but in the shipped bundle every byte counts: the segmentsprivate,colour,dimension, andtypographyrepeat across most variables and account for a meaningful chunk ofbase.css.This PR introduces a build-time mangler that rewrites those segments to single-letter abbreviations in the bundled output, while keeping every source file (component SCSS, token-sync's standalone CSS) using the full readable names.
Pipeline
token-syncemits atokens-mangle-map.jsonmanifest alongside its CSS output.New files:
token-sync/src/mangle-token-name.ts,token-sync/src/manifest-emitter.ts.mangleVariableNameapplies a small abbreviation dictionary segment-by-segment to each CSS custom property name produced by the build:The four entries are deliberately the highest-frequency repeated segments — Phase 1 of the dictionary. More abbreviations can be added incrementally; each addition is collision-checked at build time.
buildNameMapwalks the full set of names emitted by the build, deduplicates, and throws on collisions so a poorly chosen abbreviation can never silently merge two distinct tokens into the same CSS variable.emitTokensMangleMapwalks the DTCG token trees (primitives + canonical light theme — symmetry across other themes is already asserted by the existingassertInputsAreBuildablecheck) and writes a sortedoriginal → mangledmap totoken-sync/css/tokens-mangle-map.jsonalongside the standalone CSS files.A new PostCSS plugin (
postcss-mangle-bpk-vars) consumes that manifest at webpack build time.New file:
scripts/webpack/postcss-mangle-bpk-vars.js.For every CSS file webpack pipes through it:
decl.proprewritten (catches the:root { … }block coming fromtheme-backpack-*.css).var(--bpk-…)references inside declaration values get rewritten viaVAR_REF_PATTERN(catches all the component code that consumes the tokens).The manifest is loaded eagerly at plugin construction so a missing/broken manifest fails fast at webpack startup rather than mid-build, and is cached per-path so it's not re-read for every CSS file in a single run.
An optional
strict: truemode throws onvar(--bpk-…)references that aren't in the manifest — useful in CI to catch typos and tokens that haven't been promoted into the design system. Off by default, so legacy component-local custom properties (e.g.--bpk-button-svg-display) keep flowing through unchanged.Wire-up in
scripts/webpack/postCssPlugins.js.The new mangler runs after the dedupe plugin from [CLOV-1637] Phase 1: Drop legacy fallback declaration in bpk-themeable-property and delete duplicate dark style #4630 and before flexbugs-fixes / autoprefixer:
Order matters: dedupe relies on the light theme file on disk (which still uses long readable names, since token-sync ships the unmangled form), so it must run before names get rewritten.
Where mangling does NOT happen
This is important enough to call out: only the webpack-bundled CSS is mangled. Token-sync's standalone
theme-backpack-light.css/theme-backpack-dark.cssfiles keep their full readable names (the build-css transform comment is updated to spell this out). Anyone consuming those files directly — or anyone who wants to opt out of the mangler entirely — is unaffected.This means component authors continue writing
var(--bpk-private-button-colour-bg-primary)in their SCSS. The mangling is invisible to them; the bundle is the only place the short form appears.Scope
var(--bpk-…)call site continues to use the long readable name. Only the bundled output is mangled.token-sync/css/tokens-mangle-map.json) so the consumer-side webpack build can read it without runningtoken-syncfirst. It's regenerated whenevernpm run tokens:build-cssruns.buildNameMapdoesn't trip its collision check.What this PR does not do
theme-backpack-*.cssdirectly still receive the full readable names.strictmode on the mangler. Turning that on is a separate decision once we're confident the manifest covers every legitimatevar(--bpk-…)reference in the codebase.--bpk-*custom properties (e.g.--bpk-button-svg-display) into token-sync. They simply pass through the mangler untouched.