Hacker News new | ask | show | jobs
by progval 1092 days ago
Browsing HN only needs one round-trip (fetch the HTML), maybe two if you don't have it cached (fetch the CSS).

Many apps need more round-trips, by loading assets sequentially. For example: fetch the HTML, then the JS, then the JS downloads its config, then the JS fetches some assets. Latency accumulates with every round-trip.

4 comments

No, HN is not just one request, it is 7.

And no, latency does not accumulate.

Because the browser requests assets in parallel as it loads the html.

Also, assets can easily be routed through a CDN.

Latency absolutely does accumulate for code as the parent described that cannot make a request until the previous one has returned (images linked from css files for example, or a spa with poorly chunked code). There is a lot of that code out there. "Modern" tooling and practices reduce that, but it not a solved problem for the majority of legacy code.
You describe the issue of dependencies.

You don't need modern tooling to prevent it. A server side build step to combine assets only makes things worse. Because on first load you get bombed with a giant blob of code you don't need. Or the developers get lost in the complexity of it and it becomes a giant hairball of chaos. The Twitter homepage takes 185 requests to load. AirBnB 240. Reddit 247. Look at the source code to see the chaos their build systems create.

Simply using a server side rendred html page and native javascript modules prevents all of that. The modules get loaded asynchronously. So the modules and their dependencies have time to load until all the html interface and the asynchronous assets like CSS, images etc are loaded and rendered. And then the modules can kick in.

Interesting for me: reddit.com made 136 requests, 2.3MB Transferred, 3.0MB resources loaded by page ireddit.com 254 requests, 19.2 MB!! transferred 22.3 MB resources

old.reddit.com was 10 requests, 5kB transferred, 9kB resources I tried mbasic.facebook.com and interestingly it was (not logged in) only 1 request 1.1kB transferred, 1.1kB resources

I turned off any browser level blocking, but I do have some network level ad-blocking. I wonder why you get 111 more requests for (www.)reddit.com than I do.

Those(mbasic.facebook, old.reddit) are the old/basic interfaces I use regularly and both are requirements for me, I won't use their normal websites or apps so if they get shutdown I would leave for good.

All quite true, server renders pages are the quickest route to first render, in-line your CSS for that first page and it's even quicker. All best practices for sites that fit those categories, content and e-commerce for example.

But not all sites and apps can do that, and almost certainly not for all functionality and pages. Bloat isn't just about tooling, it's organisational too. Lots of teams all working within one product.

Modern ES modules can actually be worse if not bundled on on the server or by a build system. The browser doesn't know what to request until it starts parsing the previous response, that dependency tree can be large. That literally is accumulating latency. However with progressive improvement it's not much of an issue, but again not everyone can do that.

On top of that anyone still on HTTP 1.2 will only be doing ~5 requests to the same domain in parallel.

Point is, latency does accumulate, but it doesn't have to with well designed code structure, "modern" (rediscovered 90s) techniques, and modern browser features like preload and preconnect.

I for one agree with both of you.
Sadly nowadays sites will send javascript which contains a request to fetch more javascript which contains a request to fetch more javascript which renders an html element which... wait for it... requests more javascript. This sounds like it's an exaggeration but no.

At least on newer browsers we're no longer universally loading a javascript interpreter written in javascript (though sometimes we still are!)

A lot of the JS calling for more JS is third party services that don't block render.

For web apps, what matters most is above the fold load speed + time to interactive.

In the era when React got popular but Next.js hasn't yet, we had really slow performing sites because it did exactly what you said. Then people finally figured out that pure client-side rendering apps are too slow so people started switching to server side rendering. Non-interactive websites switched to just static websites that load from CDNs.

Modern web apps and modern static websites are in a much better state than the 2014 - 2018 era.

I take your point that more-recently designed sites have moved away from this antipattern but there's still a lot of the Web that has that mid-teens "hey bro I see you like javascript so I put some javascript in your javascript" mentality.
> HN is not just one request, it is 7

For those curious, it's /, then css, js, then 2 svgs, 1 ico (favicon) and 1 1x1 gif. None over 10k over the wire (/ is ~40k before compression)

CSS, JS, y18.svg, and the GIF are fetched in parallel, so they only count once toward visible latency. triangle.svg is fetched after the CSS is done, so it does (though for me, it's done downloading before y18.svg is)
True and not true.

In modern apps, there's often additional assets loaded from Javscript calling endpoints or calling for more assets.

If you do server side rendering, there are usually fewer roundtrips.

> Browsing HN only needs one round-trip

It's never just one round-trip: the TCP handshake is one round-trip in itself, then there's the TLS handshake needing two addionnal round-trips, and only then comes the HTTP round trip. So the minimum latency you can have to load just the HTML is in fact 4 times the round-trip time. (And I left DNS aside, because the DNS resolution process involves talking to different servers that are thelselves at different distances).

> It's never just one round-trip

That’s not true. TLS 1.3 0-RTT cuts down on handshake roundtrips, taking one roundtrip to establish the TCP connection before data can be sent; and HTTP/3 (QUIC) with 0-RTT actually makes it zero roundtrip, HTTP request is sent directly and response is received in one roundtrip.

Thanks for pointing that out, it looks that my knowledge was a bit outdated.

It looks like the 0-RTT thing only work for connection resumption so it will only work if the user has already visited the site before.

Still, even without it, TIL that since TLS1.3, there's only a single round-trip and not two in the TLS handshake.

I'm long out of web dev, but... is this really how (well designed) web apps work? It seems lazy, you should be able to statically generate a list of most, if not all, assets and queue them all up simultaneously.

With only a tiny bit more effort you could improve things even further by generating 'resource packs' (just zip files really) like games do, that you can load and then unpack locally.

Which is why I get a heart attack whenever I hear people talk about forgoing bundlers and using esm imports for dependencies directly in production. Some will tell you that dozens/hundreds of small requests aren’t a problem since h2 can load them simultaneously in the same connection. What they don’t mention is the cascade of roundtrips as imported deps are parsed from scripts. Apparently they don’t care because they assume all users live 20ms from their data canters.
Sadly this seems to be industry-wide these days, so many things don't work well (or at all!) without a fast internet connection. Most recent example that's been bugging me is Explorer in Windows still connects synchronously to network shares as far as I can tell.
As things get faster developers have to introduce lazier practices to maintain the same level of shittiness. Eliminate parallel request limit and they spam you with hundreds of scripts. Eliminate head of the line blocking and they come right back at you with cascade of dependencies blocking. Of course “things get faster” isn’t universal when it comes to network latency and throughput, so the experience strictly worsens for a subset of users.
Do you think that's why Reddit takes 5 seconds to show a cookie banner?