I throttled our marketing site to Fast 3G and the 400 KB of JavaScript was not the problem

2026-11-03来源 dev.to WebDevEnglish

We measured four live pages twice each, once unthrottled and once at 4x CPU throttling with 1.6 Mbps down and 150ms of latency, which is roughly what DevTools calls Fast 3G. Cache disabled both times. The metrics come from PerformanceObserver with buffered: true registered before navigation, so nothing is inferred from a lab score.

The four pages: the homepage, the FAQ, a free tool and a comparison page. Three of them are static prose and one is the only page on the site with a product mock on it.

The numbers

page load, fast load, throttled FCP throttled LCP throttled long tasks CLS
/ 762ms 12,334ms 1,872ms 4,248ms 0 0
/faq 224ms 2,622ms 1,536ms 1,536ms 3 (283ms) 0
/tools/round-planner 309ms 2,637ms 1,500ms 1,500ms 4 (352ms) 0
/compare/kahoot-for-pub-quiz 458ms 2,620ms 1,532ms 1,532ms 3 (269ms) 0

Four things in that table are worth more than the rest.

TTFB is not a variable

Every page, both conditions, answered its first byte in 20 to 27 milliseconds. 70 of our 72 public pages are prerendered and served from the edge, and the throttle profile's 150ms of latency barely registers against a cache hit because the response is already sitting in Frankfurt. There is nothing to optimise at the front of this waterfall, which is the main reason the rest of it is so visible.

The three prose pages converge to the same number

2,622ms, 2,637ms and 2,620ms. A 17 millisecond spread across three pages with different content, different lengths and different components. They converge because they ship the same thing:

page HTML over the wire HTML decoded JS requests JS bytes total requests total bytes
/faq 12,550 77,981 18 357,997 44 453,113
/compare/kahoot-for-pub-quiz 12,484 80,580 18 357,997 49 460,052
/tools/round-planner 11,479 72,401 19 362,708 49 463,836

The identical 357,997 bytes on two pages is not a rounding coincidence, it is the same 18 chunks. A page of prose on this site costs about 12 KB of HTML and about 358 KB of JavaScript, and the JavaScript dominates by a factor of thirty.

Then look at the third row. /tools/round-planner is a working running-order planner: you add rounds, set lengths, pick where the break goes, and it recomputes the schedule. Compared to the FAQ page, which has no interactive element at all, it ships one more chunk and 4,711 more bytes. The entire feature costs 4.7 KB. The 358 KB underneath it is what the framework costs to be there.

LCP and FCP are the same millisecond, because the page has nothing bigger than its own text

On all three prose pages, the largest contentful paint element is a paragraph:

/faq <dd class="text-muted-foreground mt-2 leading-relaxed"> "A device to host from with a web browser, meaning a laptop, tablet or ..." /compare/kahoot-for-pub-quiz <p class="text-muted-foreground leading-relaxed"> "Kahoot is built around speed. Its scoring rewards fast answers heavily ..." /tools/round-planner <p class="text-muted-foreground leading-relaxed"> "A round of ten is not ten questions long. It is ten questions read twi ..." 

FCP and LCP are reported at the same timestamp, to the millisecond, on each of them. There is one <img> on each page, the 606 byte header logo, and no hero. So the moment anything paints is the moment the biggest thing paints, and improving LCP on these pages means improving first paint, which means the CSS and the font, not the JavaScript.

The homepage takes 12 seconds, and not on script

The homepage is 2,460,589 bytes over 49 requests. 1,869,539 of those bytes, 76 per cent, are two files:

demo-2.webp 953,385 bytes finished at 12,329ms demo-3.webp 915,548 bytes finished at 12,148ms 

The load event fires at 12,334ms. Those two requests are the load event. They are CSS background images, which means Next's image optimiser never sees them, so they ship at their full authored size while the hero image beside them, which is an <img>, is served through the optimiser at 76,458 bytes.

We have written about that optimiser asymmetry before. What the throttled run adds is the scale of it in time rather than in bytes: the same page is 762ms unthrottled and 12,334ms at Fast 3G, and the 11.5 second difference is almost entirely two decorative screenshots nobody is reading.

The hero itself is the LCP element, and it arrives at 4,248ms, 2.4 seconds after first contentful paint:

/_next/image?url=%2Fdemo-1.webp&w=3840&q=75 

w=3840 is the largest entry in Next's default size list. On a 1512 pixel window at device pixel ratio 2 the browser wants about 3024 pixels of image, and 3840 is the next size up, so that is what the srcset resolves to. 76,458 bytes is a good result for an image that large. It is still the slowest paint on the site.

Cumulative Layout Shift is exactly zero everywhere

Zero shifts recorded, not just a score under the threshold, on all four pages in both conditions. We would like to claim credit and can only claim some. The things that usually cause shift are things we do not have: no ad slots, no cookie banner, no consent dialog, no late-injected newsletter bar, no web font swapping into a metrically different fallback, and no client-side data fetch that replaces a placeholder with content of a different height. A page that is server-rendered prose with one small logo has very little left to shift.

The inversion nobody predicted

Long tasks, meaning main thread blocks over 50ms, measured only under throttling because at full speed there were none anywhere:

page long tasks total blocking longest
/ 0 0ms n/a
/faq 3 283ms 143ms
/compare/kahoot-for-pub-quiz 3 269ms 137ms
/tools/round-planner 4 352ms 137ms

Our heaviest page, the one that takes 12 seconds and ships 2.4 MB, blocks the main thread for zero milliseconds. Our lightest pages block it for a third of a second.

The homepage's weight is bytes arriving over a slow pipe, which costs wall clock and no CPU. The prose pages' cost is hydrating a tree of server components on a quarter-speed processor, which costs CPU and almost no bytes. They are two completely different problems that both show up as "the page feels slow", and a single number like a Lighthouse score blends them into something you cannot act on.

The practical reading: on the content pages, the fix is less JavaScript, because 358 KB is being parsed and executed to make static prose interactive in no way at all. On the homepage, the fix is two <img> elements instead of two CSS backgrounds, and nothing to do with script.

Reproduce it

Open DevTools, Performance panel, set CPU to 4x slowdown and Network to Fast 3G, tick "Disable cache", and record a reload of the homepage. Then do the same on the FAQ. Watch where the time goes in each: a long thin network tail on the first and a cluster of yellow on the second. Both pages are public, no account needed, and the two 950 KB images are visible in the Network panel sorted by size.

原文:https://www.a8q9.cn/en/article/i-throttled-our-marketing-site-to-fast-3g-and-the-400-kb-of-javascript-was-not-t-d27102.html

相关文章