Public: anyone can read this; the crew can change it.
The same twenty icons, once each: the front door stops re-sending its drawings #154
Check · Review · Land · Live done — Landed and live in production.
Pushed. Pull description follows.
shipped production is serving it deploy 76ab860
Sign in to join this conversation.
new above
offline
Pushed. Pull description follows.
---
icon()inlined its whole Lucide drawing on every call, so a list of thirty rows shipped the same twenty paths a hundred times. It now renders the 16px slot with a one-line<use href="#i-name"/>inside it, and theviewBox,fill,strokeand cap/join attributes move onto the<symbol>, which is where they belong once a drawing is defined once.iconSprite()(src/web/icons.ts) reads the page's own rendered markup for those references and emits exactly the icons it found, in a zero-sized<svg class="sprite">at the end of<body>— that is the choice the issue asked me to name: no collector threaded through components, and a<use>earlier in the document resolves against it fine.layout.tsbuilds the body first, scans it (~75 µs on a 110 KB page) and appends the block before the script.Weights, measured locally by booting a real forge: a 30-row issues list goes 82,472 → 76,392 b with its icon markup dropping 19,058 → 12,998 b; a repo page 50,381 → 48,399 b; a fresh account's studio
/64,248 → 63,036 b (only 28 icon uses on an empty forge, so the whole saving is there to see but small). On the census this issue measured — 98 of the 104 uses, across the same 20 distinct drawings — the icon markup goes 32,136 → 16,893 b, −15.2 KB;test/web.test.tsasserts that delta stays above 15 KB, so the deployed front door should land near 96 KB instead of 112.6 KB. Look first aticonSprite/inlineIconsinsrc/web/icons.tsand theshellsplit inpage().The one thing that needed care beyond the issue: markup that lands in a document it does not own cannot reference a sprite it did not ship.
fragment()andthreadFragmenttherefore expand their references back into the nested<svg>a<use>would have instantiated (same pixels, no ids to collide), andliveRegionsJs— which re-fetches a whole page and swaps one region'sinnerHTML— now carries the fresh page's sprite across first, so a region that swaps in an icon the first paint never used still draws. The CSP is untouched; the only stylesheet change is one.spriterule taking the block out of flow. New tests: the slot's exact markup and both sizes, the spinner'sico-loaderclass, a dozen rows sending the issue glyph's path once, symbols-defined equalling icons-used exactly on three pages, and a fragment that contains no<use>at all. No snapshot held icon markup, so none were updated.What I did not do:
themeGlyphstays inline (one per page, nothing to fold), and I left the block out of<head>, which would have meant rendering the body twice or threading a collector. Note for the check: six tests in this suite fail in my sandbox because git-over-HTTP pushes are blocked here — the same six fail identically onmainat this commit, and my six new tests pass.🤖 Generated with Claude Code
Closes #134