Repository navigation
perf: drop 566 KB and 26 requests from the homepage (−36%) - #74
Merged
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Four changes, no new dependencies, zero client-JS delta -- these are
request and payload wins, which is what the perf-budget gate's own
docblock says it structurally cannot see.
The brand `<Link href="/">` in the shell was prefetching the homepage on
EVERY page: 77 KB of RSC payload, 80.5 KB on `/` itself. `prefetch={false}`
plus a hand-warm on pointer-enter and touch-start keeps the instant
navigation for anyone who actually aims at it. The bottom bar's 13
utility links got the same treatment, which was 28 RSC requests and
148 KB on `/` alone.
The search corpus (`/search-index.json`, 146 KB on the wire) was
prefetched unconditionally on idle. It now warms on intent instead.
`onFocus` was already wired, so keyboard users were never affected;
`onPointerEnter` covers the mouse path, so both reach the field warm.
`lib/status-checks.ts` made two fetches that exceeded Next's 2 MB data
cache ceiling, so every build logged `Failed to set Next.js data cache`
for a 3.7 MB registry.json and a 16.8 MB MCP snapshot, and neither was
ever cached. They are now `cache: "no-store"`, with the three derived
reads in `app/status/page.tsx` wrapped in `unstable_cache` at the same
hourly revalidate. 383 bytes of cache now hold what was costing a
1,078,509-byte entry plus two refused ones. Both warnings are gone.
Measured locally against `next start`, same harness both sides, CDP
`encodedDataLength`, 16s settle so media completes:
/ 1592 KB / 64 req -> 1026 KB / 38 req
/components/accordion-latch 698 KB / 85 req -> 519 KB / 57 req
/components/hero-particles-webgl 963 KB / 85 req -> 784 KB / 58 req
/install 629 KB / 59 req -> 456 KB / 33 req
/preview/<slug>/embed 372 KB / 21 req -> 372 KB (shell absent)
LCP 524 -> 200ms, domInteractive 599 -> 280ms, load 754 -> 447ms on `/`.
Request-count deltas are the solid numbers; local LCP and TTFB are noisy.
On production (brotli) the removed resources measure 146 KB, 77 KB and
~67 KB, so `/` projects 1296 -> ~1012 KB and every other page drops
~144 KB. That after-column is each removed resource's own measured prod
size, NOT a second production run -- this branch is not deployed.
Deliberately NOT touched: the 985 KB largest chunk. It is `three` plus
@react-three/fiber, and it is already correctly split -- referenced by
zero prerendered HTML, reachable only as an async import() target from
the 55 KB registry lazy map. A full 14-screen catalog scroll on
production (54 iframes, 1200 requests) pulls it 0 times, and the three
`hero-particles-webgl` links on `/` render as a FeaturedCard with a video
and poster, never an iframe, so the homepage has no path to it at all.
The obvious lever is also dead: narrowing that component's
`import * as THREE` buys zero bytes, because r3f calls `extend(THREE)` on
the whole namespace to build its JSX catalogue. Dropping it down means
hand-driving WebGL in a registry component, for one component, with real
behaviour risk.
Also worth recording: the perf budget is not near-exhausted.
`scripts/test-perf-budget.ts` sets `TOLERANCE = 1.1`, so CI fails above
6979 KB total and 1084 KB largest -- 656 KB and 99 KB of real headroom,
not the 23 KB and 1 KB the raw budget numbers suggest.
Signed-off-by: Nik <84yk8btb9f@privaterelay.appleid.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
nikolas-sapa
force-pushed
the
perf/weight-and-ttfb
branch
from
October 13, 2026 12:51
d8ff8d7 to
67e18b9
Compare
This branch was successfully deployed
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 changes, no new dependencies, zero client-JS delta — these are request and payload wins, which is exactly what the perf-budget gate's own docblock says it structurally cannot see.
Measured locally (
next start, same harness both sides, CDPencodedDataLength, 16s settle)//components/accordion-latch/components/hero-particles-webgl/install/preview/<slug>/embedLCP 524 → 200ms, domInteractive 599 → 280ms, load 754 → 447ms on
/. The request-count deltas are the solid numbers; local LCP and TTFB are noisy.What changed
The brand link was prefetching the homepage on every page — 77 KB of RSC payload, 80.5 KB on
/itself. Nowprefetch={false}with a hand-warm on pointer-enter and touch-start, so aimed navigation stays instant. The bottom bar's 13 utility links got the same treatment: that was 28 RSC requests and 148 KB on/alone.The search corpus (
/search-index.json, 146 KB on the wire) was prefetched unconditionally on idle. It now warms on intent.onFocuswas already wired so keyboard users were never affected;onPointerEntercovers the mouse path.The data-cache cliff is closed.
lib/status-checks.tsmade two fetches over Next's 2 MB ceiling, so every build loggedFailed to set Next.js data cachefor a 3.7 MBregistry.jsonand a 16.8 MB MCP snapshot — and neither was ever cached. Nowcache: "no-store", with the three derived reads inapp/status/page.tsxwrapped inunstable_cacheat the same hourly revalidate. 383 bytes of cache now hold what was costing a 1,078,509-byte entry plus two refused ones. Both warnings gone.Production projection, stated honestly
The removed resources measure 146 KB, 77 KB and ~67 KB on production (brotli), so
/projects 1296 → ~1012 KB and every other page drops ~144 KB.That after-column is each removed resource's own measured prod size, not a second production run — this branch isn't deployed.
Deliberately NOT touched: the 985 KB chunk
It's
three+@react-three/fiber, and it is already correctly split:import()target from the 55 KB registry lazy maphero-particles-webgllinks on/render as aFeaturedCardwith<video>+ poster, never an iframe — the homepage has no path to it at allThe obvious lever is dead too: narrowing that component's
import * as THREEbuys zero bytes, because r3f callsextend(THREE)on the whole namespace to build its JSX catalogue. Getting it down means hand-driving WebGL inside a registry component, for one component, with real behaviour risk.The perf budget is not near-exhausted
scripts/test-perf-budget.tssetsTOLERANCE = 1.1, so CI fails above 6979 KB total and 1084 KB largest — 656 KB and 99 KB of real headroom, not the 23 KB and 1 KB the raw budget numbers imply. Worth knowing before anyone shaves something unrelated to "make room".Verification
npx tsc --noEmit— exit 0npm run test:source-invariants— 0 problemsnpm run test:perf-budget— 6323 KB / 985 KB, byte-identical before and after🤖 Generated with Claude Code