Repository navigation
build(signals): pin mangled _-prop names in a checked-in map - #4503
Conversation
terser hands out short property names in first-seen order, so one added or renamed field reshuffled names across the prod/observe trees and moved brotli on unrelated size scenarios. scripts/mangle-props.json seeds the shared nameCache per tree; existing fields keep their names, new fields take unused names, removed fields drop out. Generated from next @ 643a7a7: dist is byte-identical. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015hPxMkC3jg3Uivh65gvaf2
A cache hit restored dist but not a map the build wrote back, so the next build re-derived names the cached dist did not use. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015hPxMkC3jg3Uivh65gvaf2
…-x1ore2-mangle-cache
|
Size (brotli, eager entry chunk)
|
Coverage Report for CI Build 41120509370Coverage remained the same at 78.1%Details
Uncovered ChangesNo uncovered changes found. Coverage RegressionsNo coverage regressions found. Coverage Stats
💛 - Coveralls |
Merging this PR will not alter performance1 warning
Comparing Footnotes
|
Before:
scripts/mangle-props.mjsstarted each build from an empty tersernameCache. Terser hands out short property names in first-seen order across the sorted file walk, so one added field renamed every field seen after it. Adding one field in core renamed 46 of 139 prod fields across 18 files, and one inboundaries.jsrenamed 58. Size scenarios that never include the changed file still moved brotli. With one new field inboundaries.js, the core floor moved +6 B, hello world +7 B, createStore −22 B and isPending/latest +13 B.After: existing fields keep their names, and only a new field gets a new name, so scenarios that don't contain a change stay at exactly 0 B. Today's dist is byte-identical, and every size scenario is unchanged: hello world 9,973 B, core floor 7,413 B.
How:
packages/signals/scripts/mangle-props.jsonholds each tree's_field → namemap (prod: 139 fields, observe: 168), generated from next @ 643a7a7.nameCachefrom it. A new field takes terser's own fallback, the first base54 name the cache doesn't hold._token no longer appears in the unmangled tree is dropped, so its name is free again. Renaming_pendingValueto_stagedValuekeptue, and every scenario moved 0 B.turbo.jsonlists the map among the signals build outputs, so a cache hit restores it withdist.What this doesn't fix: on scenarios that do contain the change, brotli still swings by up to about ±100 B for tiny inputs. With the same pinned build and the new field forced to
It,Qq,Wxorzz(identical minified size), page base moved −53 to +74 B and router +7 to +105 B. That noise comes from brotli itself, not from the mangler.Tests: signals 6080 passed / 17 expected fail.
tests/dist-artifacts.test.tspasses 36/36 against pinned dists with a new field.Generated by Claude Code