My homepage took 8 seconds to load. I threw a CDN, a cache, and lazy-loading at it. It was still slow.

2026-11-03来源 dev.to WebDevEnglish

My homepage took eight seconds to load. Eight full seconds of a spinner — long enough to make tea, long enough that anyone on a phone on a train had already closed the tab and forgotten we existed.

So I did what you do. I made it faster. I put a CDN in front of it. I added a caching layer. I lazy-loaded the images, code-split the bundle, slapped a loading skeleton over the blank screen so at least it felt like something was happening. I spent the better part of a month adding fast things to a slow site.

It was still slow. Not quite eight seconds anymore — but nowhere near fast, and worse, I was out of fast things to add. I had bolted every optimization I knew onto the outside of the app, and the app just sat there, taking its time, completely indifferent to all of them.

The month I spent making it faster taught me almost nothing. The afternoon I finally spent understanding why it was slow fixed it. And the gap between those two things turned out to be the whole point.

The pile of fast things

Here's the part I'm a little embarrassed by, because it's such a tell.

Every single thing I added was a reasonable thing to add. A CDN is good. Caching is good. Lazy-loading images is good. Code-splitting is good. None of it was wrong. If you'd looked at my list of changes, you'd have nodded along — that's the performance checklist, that's what you're supposed to do.

But look at what the list actually is. Every item on it is a way to make work happen faster, or closer to the user, or later. Not one of them is "do less work." I had a page that was doing an enormous amount of unnecessary work, and my entire response was to find faster and faster ways to do the unnecessary work. A CDN so the wasted bytes arrive from a nearer city. A cache so I only have to do the pointless thing once in a while instead of every time. A skeleton screen so the user feels better about waiting for something that never needed to take that long.

I was optimizing the app instead of understanding it. And those are not the same activity — they're barely even related. One of them I could do fast, from memory, off a checklist, without ever opening the slow path and looking at it. The other one required me to actually sit down and find out what my own homepage was doing for eight seconds. Guess which one I did for a month first.

What it was actually doing

When I finally ran a trace instead of adding a feature — when I just watched, request by request, what the page did between "user hits enter" and "page appears" — the answer was almost funny.

To render the homepage — a greeting, a nav bar, and three little cards — the server was taking a guided tour of the entire database before it sent a single byte.

It loaded the user. Then, using something off the user, it loaded their organization. Then, using something off the organization, it loaded every project in that org. Then, for each project, one at a time, it loaded that project's most recent activity so it could maybe show a timestamp on a card the user would probably scroll right past. Each of those requests waited politely for the one before it to finish. A waterfall — one long single-file line of queries, each one blocking the next, the whole page holding its breath until the last straggler came back.

Eight seconds. To draw a greeting and three cards. The server wasn't slow. The database wasn't slow. The site was slow because it had decided, somewhere, years ago, that it couldn't render the top of the page until it had fetched the bottom of a data structure almost nobody looked at.

None of my optimizations touched this, because none of them could. A CDN can't parallelize a waterfall. A cache only helps the second visitor, and only if the data's the same, which it wasn't. Lazy-loading images does nothing for a page that's blocked on a chain of API calls before it paints at all. I'd been tuning the delivery of a payload the page should never have been waiting on in the first place.

The fix was understanding, not code

The actual change was small and boring, which is how you know it was the right one.

Render the shell immediately — the greeting, the nav, the cards' outlines — with the handful of things the first screen genuinely needs. Fetch those few things in parallel instead of in a chain. Everything else — the per-project activity, the stuff below the fold, the data for the card nobody clicks — load it after the page is already on the screen, or when someone actually asks for it.

That was it. The page went from eight seconds to about one. Not because I'd added a faster anything, but because I'd finally asked the question I'd spent a month avoiding: does this request need to happen before the user sees the page — does it need to happen at all? For most of that waterfall, the honest answer was no. It had just never occurred to anyone to ask, because adding the next fetch had always been easier than questioning the last one.

The code diff was tiny. The understanding behind it was the entire job.

The part that isn't free anymore

Here's the reframe, and it's the whole point.

Adding a fast thing is nearly free now. I can ask a machine to add a caching layer, wire up a CDN, memoize a component, lazy-load a route, and have plausible, working code back before my coffee's cool. So can you. The performance checklist — the whole catalogue of add-this-to-go-faster — has basically collapsed to a sentence and a few seconds of waiting. Adding speed, as an activity, has never been cheaper or more tireless.

But none of that is the same as knowing why your app is slow, and that part didn't get cheaper at all. Finding the eight-second waterfall meant holding the actual shape of the request graph in my head — what calls what, what waits on what, what the first screen truly needs versus what got loaded "just in case" by someone who's long gone. No tool handed me that. A tool will very happily add a sixth optimization on top of a problem it doesn't understand, because adding is exactly what it's good at. It will not, unprompted, tell you that the first five were treating a symptom.

You can't cache your way out of not understanding your own app.

The tools let me bolt on five optimizations in an afternoon. It took me a week to find the one request that was the whole problem — and that week, not the afternoon, was the actual engineering. Speed isn't something you add. Slowness is something you understand. The adding got free this year; the understanding didn't, and it never will.

To be clear — this is not "optimizations are bad"

I need to be fair here, because the lazy version of this post is "real engineers profile, juniors just add a CDN," and that's garbage.

I'm not anti-optimization. The CDN stayed. The caching stayed — it's genuinely useful now that the page isn't doing pointless work behind it. Lazy-loading, code-splitting, the skeleton screen: all still there, all still earning their keep. Adding fast things is good, and on a page that's already doing the right amount of work, that checklist is exactly how you squeeze out the last stretch. I'd add every one of them again.

The point is narrower, and I think more useful: adding speed was never the scarce part, so getting faster at adding it didn't make my site fast — it just let me pile optimizations on top of a problem I hadn't looked at. The scarce thing — the only thing that actually took eight seconds down to one — was the judgment to open the slow path and ask what work was even happening and whether it needed to. The tools made the adding free and did absolutely nothing about that question. They can't. They optimize confidently in whatever direction you point them — including straight onto the pile.

Why this is exactly how I build now

I build an agent platform now, and this one slow homepage is more or less the whole thesis of it.

The industry's reflex this year is to worship the author — the thing that generates. Look how much it ships! A caching layer from a sentence! But an author with no counterweight doesn't hand you a fast app. It hands you my homepage: five reasonable optimizations stacked confidently on top of a waterfall nobody questioned, because generating the next fast-thing was always easier than understanding the slow one underneath. I did it by hand for a month. The author is how the pile of fast things gets built.

So the part I care about isn't the author — I already assume the author. Everyone has one now. What I'm hunting for is the skeptic and the human. The author adds the optimization, fast and free. The skeptic is the part that asks the question I avoided for a month — does this request need to happen at all? what is the first screen actually waiting on? — and whose best output is often "delete four of these calls," not a sixth one. And the human is the one who owns the real person on the other end — someone on a phone on a train, watching a spinner for eight seconds, one thumb-twitch from gone. Author, skeptic, human. That separation is the entire shape of xenition — and it's the same thing one slow page taught me the hard way: generating the fast thing is free and always will be; knowing why it's slow, and what the person on the other end loses while they wait, is the whole job, and the only part anyone ever actually pays for.

My homepage didn't get fast when I ran out of optimizations to add. It got fast the afternoon I finally understood what it had been doing all along.

Next time your app is slow, don't reach for the checklist first. Open the slow path and watch what it actually does — and ask how much of that work was ever needed at all.

原文:https://www.a8q9.cn/en/article/my-homepage-took-8-seconds-to-load-i-threw-a-cdn-a-cache-and-lazy-loading-at-it--0d3b53.html

相关文章