DEV Community

Bala Krish
Bala Krish

Posted on

I got my React SPA to 95/100/100/100 on mobile PageSpeed

81/93/92/92 → 95/100/100/100. Mobile, simulated slow 4G. Here's everything I did, including the stuff that backfired.

The site is SudoRank - React 19, TanStack Router, Tailwind 4, running on Cloudflare Pages with 523 prerendered pages.

Before: 81/93/92/92

PageSpeed before - 81/93/92/92 - single 313 KiB gzip bundle, zero code splitting, Google Fonts from CDN, Clarity and GA loading eagerly. Basically every mistake you can make.

Fonts

Google Fonts means three origin connections on slow 4G. Tried @fontsource-variable packages first - score tanked 81 → 67, fonts got bundled into JS. Downloaded the .woff2 files instead, @font-face with font-display: swap in public/fonts/.

Analytics

Wrapped Clarity + GA in a setTimeout(fn, 3500). Page is rendered by then. GA still picks up the pageview, Clarity replays from initialization.

Also tried font preloads here - score went 77 → 74. Preloads fought the JS bundle for bandwidth on 1.6 Mbps.

Code splitting

TanStack Router has built-in code splitting. I hadn't turned it on. 22 routes in one 313 KiB bundle, including xterm.js (342KB raw).

TanStackRouterVite({ autoCodeSplitting: true })
Enter fullscreen mode Exit fullscreen mode

Homepage JS went from 313 KiB to ~164 KiB gzip. FCP 3.0s → 2.1s, LCP 3.9s → 2.6s. This was the entire Performance improvement.

The other three scores

SEO: Cloudflare was injecting non-standard directives into robots.txt. Wrote my own. 92 → 100.

Best Practices: Four CSP violations from analytics domains I hadn't whitelisted. Added them. 92 → 100.

Accessibility took two rounds. First was a low-contrast text color and a heading skip (h1 jumped to h3). That got it from 93 to 95. The second one was harder - a purple label on a card with a semi-transparent purple background. The contrast checker said it was fine because I was testing against the base dark bg, not the composited result. Compositing rgba(139,92,246,0.06) onto #13131A gives something like #1A1727, and the contrast dropped to 4.14:1. Changed to a lighter purple. 95 → 100.

Where it ended up

After: 95/100/100/100

PageSpeed after - 95/100/100/100

Metric Before After
FCP 3.0s 2.0s
LCP 3.9s 2.6s
TBT 30ms 0ms
Speed Index 3.0s 2.0s

Getting to 100 would mean inlining critical CSS and shrinking React core under 80KB. Google ranks on Core Web Vitals, not Lighthouse scores. All CWV are green.

I grew up in Trichy with dial-up. Pages rendered one line at a time. PageSpeed's simulated slow 4G isn't far off. We used to just wait. Now a 3-second load and people think your site is broken.


SudoRank if you want to run PageSpeed on it yourself.

Top comments (0)