perf: lazy-load HeroBackground (off mobile critical path)#94
Merged
Conversation
HeroBackground is a ~1100-line canvas-based decorative component used
only on the homepage. It already self-suppresses on viewports ≤ 639px
(useIsHeroCanvasSuppressed), so on every mobile visit the entry bundle
was downloading, parsing, and evaluating the component just for its
render to be a no-op.
Mobile Lighthouse on prod showed LCP = 2.6s (h1 hero headline, per the
existing in-source comment), held back by the entry bundle's parse +
execute cost. Removing HeroBackground from that bundle is the lowest-
risk lever available — it's strictly decorative and already invisible
on mobile.
Change:
* Convert the HeroBackground import to React.lazy, so it gets its own
chunk (~17 KB raw / ~6 KB gz, plus ~3 KB gz that fell out of the
shared seo chunk).
* Gate the <HeroBackground /> mount inside HeroSection on a fresh
matchMedia('(max-width: 639px)') check (with a resize listener for
parity with the original suppression hook). Mobile never fetches
the chunk at all; desktop fetches it after the entry parses and
the canvas appears a few hundred ms after first paint — invisible
for a background.
Bundle effect (vite build):
before: entry 487 KB raw / 144 KB gz
after: entry 470 KB raw / 138 KB gz (-17 KB raw / -6 KB gz)
+ HeroBackground 17 KB raw / 6 KB gz (desktop only)
Tests: 276/276 green.
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
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
`HeroBackground` is a ~1100-line canvas-based decorative component used only on the homepage. It already self-suppresses on viewports ≤ 639 px (see `useIsHeroCanvasSuppressed` inside the component), so on every mobile visit the entry bundle was downloading, parsing, and evaluating ~17 KB raw of code purely so the component could render a `null`.
Mobile Lighthouse on prod (just measured) showed:
` — confirmed by an existing in-source comment at `src/pages/HomePage.tsx:156`
So the highest-leverage lowest-risk lever is shrinking the entry bundle by removing eager-loaded code that mobile never uses. HeroBackground fits exactly: decorative, mobile-suppressed, optional on desktop.
Change
Bundle effect (`npm run build`)
Net mobile critical-path savings: ~9 KB gz off the entry-and-shared chunks; 17 KB raw never downloaded on mobile.
What I'm NOT doing here
The user explicitly ruled out SSR / Vike for this iteration. This is the smallest-safe-fix variant. If the post-merge re-measurement shows LCP didn't drop below 2.5 s, the next options are (a) further code-splitting of the 122 KB `Heading` chunk (which is really the framer-motion-bearing shared chunk, despite its name), or (b) static prerendering of the homepage hero.
Test plan