perf(build): shrink guest JS and font atlases - #409
Draft
lfkdsk wants to merge 4 commits into
Draft
Conversation
Enable Bun's whitespace-only minification while keeping identifier and syntax minification disabled. Fully minified output overflowed an ESP32-P4 QuickJS 8 KB parse stack; another variant parsed for four minutes and triggered its five-second watchdog. Keep the behavior covered by the guest-minify regression test and documented across the build references. Same-source desktop QuickJS smoke is not PSP, Vita, or ESP32-P4 device validation.
…terals The OSK needs no app.runtimeText declaration only because osk-layout.ts writes every key as a source literal that the pass-1 codepoint harvest collects. Derive the required set from the live OSK_LAYERS table and assert each insertable glyph and key-cap label is in the collector's textCodepoints for the table source. A key rewritten to String.fromCharCode(64) makes the test fail with U+0040 missing.
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.
Four commits that shrink what a guest ships, reviewable one at a time. They sit
in one branch because all four touch
tools/build.tsand the build-pipelinedocs; splitting them into separate PRs would just move the conflicts.
perf(build): minify guest bundle whitespacePass 2 switches from
minify: falsetominify: { whitespace: true, identifiers: false, syntax: false }.Six Solid apps (hero, launcher, gallery, music, settings, cards) go from
834,973 B to 584,777 B of JS (−29.96%). Hero is 136,270 → 94,655 B; the Vue
Vapor build −29.40%, Octane −27.60%. Every measured PAK is byte-identical —
this only touches pass-2 bundling.
Identifier renaming and syntax transforms stay off on purpose. Fully minified
esbuild output once nested expressions deeply enough to overflow an ESP32-P4
QuickJS task's 8 KB parse stack, and another variant parsed for four minutes
and hit its five-second watchdog; that device needed whitespace-only output plus
a 64 KB task stack. Whitespace mode also drops ASI-safe semicolons, so the token
stream changes even though Babel reports identical AST structure and nesting
depth for all eight measured bundles.
tests/guest-minify.test.tspins the config and fails under bothminify: falseandidentifiers: true.fix(font): declare runtime text charsetsAtlases previously baked ASCII 32..126 into every slot unconditionally. Baking
only the codepoints pass 1 collected saves 186,768 B of PAK across six apps
(1,968,800 → 1,782,032 B, −9.49%); hero's font payload alone drops 92,939 B.
Pass 1 cannot see text that appears at runtime, and two apps broke when it was
subset naively:
apps/notetakes document text through the hostsvcchannel, so loading afile containing
!rendered tofu instead of the glyph.apps/zoomlabcomputes${Math.round(v.zoom * 100)}%every frame; digit6is in no source literal, so 21 of 270 frames in a zoom sweep rendered tofu —
exactly the frames whose readout contained a 6.
So digits are always baked, and an app that receives text from outside declares
it in
pocket.json:{ "app": { "runtimeText": { "charset": "ascii" } } }note,nsengineandipod-nanodeclare it and return to their unsubset PAKsize. A universal punctuation floor was measured instead and rejected: the eight
characters
noteneeds cost 84,384 B across six apps.fix(font): detect runtime text access patterns+test(font): assert every OSK_LAYERS glyph is collectedThe declaration is only useful if forgetting it fails the build. Pass 1 flags
svcPollreached through member access, shorthand/renamed/nested/default-valuedestructuring, alias chains, literal and dynamic computed keys, optional
chaining and TS casts; the build stops with a message naming
pocket.jsonandthe minimal fragment to add.
The OSK needs no declaration because
osk-layout.tswrites every typeable glyphas a source literal — which is true by accident, not by construction. The added
test derives the required codepoints from the live
OSK_LAYERStable, soturning one key into
String.fromCharCode(64)fails it.Verification
Run on this branch and on a pristine
mainworktree: the full suite has thesame five pre-existing unit failures (
pocket-packagecorpus, fouripodtouch4-installationcases), contract generation is drift-free, and thecommitted
hero-maintape hashes diverge at the same frame-0 pair on both. Herobuild timing went 1.62 s → 1.40 s cold and 0.69 s → 0.64 s warm.