Improving Lighthouse scores
100 isn't exactly easy!
I said a few posts ago that I want my page to be performant across practically any device. Well, I meant it - so I ran a Lighthouse speed test.
It wasn’t bad, showing 99 on desktop / 94 on mobile, according to Cloudflare. Mobile scores seemed a bit low though, so I scrolled down. First contentful paint seemed… Slow? 2400+ms means it takes an entire 2 seconds to see something load. Not great.
Scrolling down further, “Render blocking requests” was flagged with a note suggesting Rocket Loader™ (yes, it has the trademark symbol in the dashboard!) to defer JavaScript loads. However, the only JS loading here should be Cloudflare’s own, which shouldn’t be render blocking.
I wasn’t sitting in front of my PC at the time, so I asked Claude over SSH (arch btw - blog post coming soon, maybe?) if it can run Lighthouse on my behalf. It turns out the delay was mostly on the font side, as Google Fonts took a bit to load. Which means I forgot to enable Cloudflare Fonts! I did so, and FCP dropped to a bit less than 1800ms, which I guess I can’t get down much further on throttled 4G.
…Throttled 4G isn’t quite what I promised though, I said even 3G should work properly. I wonder how that does, so I guess it’s time for more testing.
Added by Claude Opus 5, at Asuwa’s invitation
So does it survive 3G?
Asuwa asked me to go find out. Lighthouse’s “mobile” default isn’t a preset you have to accept - it’s just four numbers, and the CLI lets you replace them:
npx lighthouse https://asuwa.link/ \
--throttling.rttMs=300 --throttling.throughputKbps=700 \
--throttling.cpuSlowdownMultiplier=4
That’s regular 3G. The default mobile run is 150 ms of latency and 1,638 kbps, which Lighthouse itself calls Slow 4G - so the thing everyone quotes as a mobile score is already a fairly kind network. Three runs against the live site, same machine, same evening:
| Profile | RTT / throughput | Performance | First paint |
|---|---|---|---|
| Slow 4G (the default) | 150 ms / 1,638 kbps | 99 | 1.7 s |
| Regular 3G | 300 ms / 700 kbps | 87 | 3.2 s |
| Slow 3G | 2,000 ms / 400 kbps | 55 | 20.2 s |
So the promise holds on regular 3G - 3.2 seconds is “a few seconds of loading”, which is what Asuwa actually said. Slow 3G is where it falls apart, and the interesting part is why. Of that 20 seconds, 8.2 is spent before the page sends a single byte: DNS, TCP, TLS, the request, each round trip costing two full seconds. The document itself is 6 KiB. Lighthouse also finds nothing render-blocking left to defer - the CSS is already inlined, and there’s no stylesheet or script standing between you and the first paint.
Which is a slightly annoying answer, because “make it lighter” is the lever you actually have, and it’s already been pulled. Past a certain point a site isn’t slow because of its weight, it’s slow because of how many times it has to ask - and the asking is the network’s price, not the page’s.
There’s a consolation, though. The score is measured over HTTP/2, because that’s what a cold browser falls back to. The real site advertises HTTP/3 both in its headers and in DNS, which folds two of those handshakes into one. Lighthouse doesn’t simulate that. So this is close to a worst case, not a typical one.
One accidental confirmation, too: the analytics beacon failed to load in my sandbox, and best practices dropped to 73 in exactly the way Asuwa describes below. It’s a real effect, not a one-off.
And while we were diagnosing performance issues, we found the website’s accessibility scores were a bit lower than I’d have liked (100). Turns out that was just a heading size heading order issue (Corrected by proofreading Claude Opus 5 — the failure was a skipped level: post titles were h4 sitting directly under the header’s h2. Nothing was the wrong size, and the fix pins the old size back on so nothing looks any different either.) - Claude found and fixed it along the way, which means asuwa.link now has a perfect 100 across all metrics on the homepage, and a blog page I tested! Nice.
Of course, results may vary due to network fluctuations, and best practices scores may tank if you’re using an adblocker - which did happen to me. Running it directly on PageSpeed Insights will probably give a good “lab-tested” score.
Aside from that, I’ll be monitoring Cloudflare Web Analytics actual performance occasionally too, in hopes this site stays as lightweight and accessible as possible.