Hacker News new | ask | show | jobs
by vjk800 1091 days ago
HN front page isn't filled with garbage and loaded with a million lines of pointless javascript like all other sites you mentioned. HN front page is 27 kb in size while, for example, reddit is 943 kb.

Performance issues with websites are entirely a self-made problem. There are plenty of fast, lean and yet very functional web pages like HN that prove that prove it.

3 comments

Size isn't even the worst of it. It's number of requests.

You need to go through a TCP handshake for every connection you open. You can reuse the connection but that means queuing requests and hitting the latency as a multiplier. Browsers also have a cap on parallel connections so when you get enough requests it queues either way. HTTP/2 reduces the problem with multiplexing but it still doesn't go away.

If your app has to make 40 requests pulling in js files, CSS files fonts, API calls etc. to show something useful that will be visibly slow the moment a user is out of region. If it's a single server rendered piece of html it's a single request.

Then for real fun be in an enterprise environment with Kerberos Auth adding a load more round trips to the server. For even more fun add in a mobile browsing solution that only has ingress in a far region when the site is hosted locally!

> It's number of requests.

Absolutely. This is the prime hallmark of shitty, slow web. If you fight your battles here everything else will fall into place.

I've started building our B2B web apps where the server returns 1 final, static HTML document in response to every resource. There are no separate js/css resource URLs at all in our products anymore. Anything we need is interpolated into the final HTML document script or style tag by the server.

If you back up for a few minutes and really think about what kind of power you get with server-side rendering relative to # of requests... It's a gigantic deal. Composing complex client views shouldn't happen on the client. It should happen on the server where all of the answers already live. Why make the client go read a bunch of information piles to re-assemble Humpty Dumpty every goddamn time they want to view the homepage?

In terms of latency, the game theory for me is simple: Either do it in exactly one request, or it doesn't matter how many requests it takes. That said... caching effects are really important for many applications, and separating sources out can save you a lot of $$$ at scale. So, you will need to balance the UX and economic effects of some of these choices.

> Why make the client go read a bunch of information piles to re-assemble Humpty Dumpty every goddamn time they want to view the homepage?

Correct me if I'm wrong, but originally it was because "servers" had order-of client compute power. Ergo, it was necessary to offload as much compute to the client as possible.

And then in early js era it was because network latency and bandwidth limitations precluded server-client round-trips for anything user-interactive.

Now, we've got surplus compute and bandwidth on both sides (order-of text payloads), so caching architecture and tooling become the limiting factors.

> "servers" had order-of client compute power

Still do. Biggest difference: If you intend to serve the same complexity of web experience today that you were trying to serve 20 years ago, you will find a single MacBook would likely be enough to handle the traffic. The challenge is that we've taken advantage of the exponential compute growth over the years and now it feels like we still have the exact same scaling issues on the server relative to the client.

If you constrain your product & design just a tiny bit, you can escape this horrible trap and enjoy those 4-5 orders of magnitude. If you design your website like Berkshire Hathaway or HN, you are on the right power curve. Seriously - go open Berkshire's website right now just to remind yourself how fast the web can be if you can lock that resume-driven ego crap in a box for a little bit.

It's very fast. It's almost unusable on a phone. That's not necessary though - I don't think you need much fanciness to make those tables not look teeny on the phone, just a little less pixel and size hard coding I think?
I am 99% sure you could solve this with a media query and some CSS totaling no more than 1KB.
Ever watched how many requests are fired off when opening the Telegram Web emoji window in any browser cache? Open it for yourself with developer tools open and cry.
For the record: a PWA can also be served by a single request, it's called hydration.

My issue with these kinds of discussions is that they're inevitably using outright false arguments.

You can make a well performing website through SSR and a backend templating language, yes.

However , In a business setting with lots of developers this usually becomes an abhorrently performing website despite the SSR with the same templating language.

You can make a pwa with any of the usual frameworks and it's going to perform wonderfully... The bad performance begins when people start to write terrible code or just keep adding dependencies to cyberstalk their users.

But doing the same in the backend puts you into the same position wrt poor performance, so it's just not an argument for or against SPAs.

It's totally fine if you decide to write your website with a SSR stack however, and it could very well be the better choice for you, depending on how your skillset is aligned with the technology.

>You can make a well performing website through SSR and a backend templating language, yes.

>However , In a business setting with lots of developers this usually becomes an abhorrently performing website despite the SSR with the same templating language.

I'm not sure this follows. It's harder to do client side rendering because your data is across a slow HTTP barrier. And the client is maintaining state which is harder than stateless.

The problem with SSR is that it's usually tied with single applications which are usually monoliths. But neither of these are requirements for SSR. If you break up your monolith into modules and/or SOA you get the best of both worlds.

But for reasons I don't understand nobody does it this way. It's either monolith + SSR or microservices + client rendering

> If you break up your monolith into modules

This is what we are doing. The server-side web monstrosity is effectively 30+ independent modules that are nested inside a common template. All of these could be worked individually without anyone stepping on each other. Anything that needs to be truly common lives in the wrapper and is rarely changed.

The only part of our business that everyone absolutely has to agree upon is the SQL schema. As long as we are talking to the data in some common language, no one will get too far off track.

They do, look up the “Backend for Frontend” pattern.
>> has to make 40 requests pulling in js files, CSS files fonts

So it's 2023 and I've been concatenation all my css, and all my js, into a single css and js request since like 2005. So a call to the site results in maybe 3 or 4 requests, not 40. But I've noticed most sites don't do this. Perhaps because I was trained when we had 28k modems not 100mb fibre?

Http/2 makes a big deal of multiplexing, but its less convincing when there are only 3 connections already.

I guess I also don't have a million separate image files, or ads etc so that likely helps.

Remember back in the old days when people used to concatenate images into imagemaps and specify the coordinates and dimensions? One image file for a whole site.

Same goes back when we could just load a single library from the Google public version (cough-jquery-cough) and then all the on-page JS was just in-tag handlers. Not that it was better but boy howdy was it faster to load.

You're probably thinking of CSS sprites, if you mean only displaying a certain portion of the image file at a time. An image map is when you display the whole image file as-is, but have different clickable links at different coordinates/dimensions.

The former is specifically for reducing requests, while the latter is more about UX.

For what it's worth, I recall the CSS sprite technique being referred to as image mapping too.

Sure, it's different from the <map> element (which is officially an image map, as you say).

But it's effectively mapping out the sections of a large image that you care about and then using CSS to display parts of it

Yeah, I vaguely recall some usage like that by the same crowd that also thinks an "anchor" is specifically a fragment link that brings you to a certain element on the same page, when in reality the word applies to all <a> tags. Sort of a casual understanding of HTML among non-devs.
I'm actually conflating both, you're right. I'm thinking of sprite-ed CSS, but also the really really old style imagemap where the same image could be clickable in multiple areas for different purposes.
I'm sure it's due to lack of standardization on the early web, but the really wild thing to me is that there are both client-side and server-side image maps (both still specified in HTML5). With the former, the various regions of the image are defined within the HTML and more or less act like regular links. With the latter, the client sends the coordinates to the server and gets redirected, so the user has no idea which pixels correspond to which URL.
Google used css sprites for Google+. They cared a lot about speed, specially for the stream, with even some CSS constructs that were known to be slow were banned from use for rendering posts.

For css sprites, you could submit an image to a folder in the monorepo, and a couple of minutes later an automated system would update the image with all the sprites, and create constants that you could you in your templates/css to use the icons with the coordinates/size of the image.

Not just in the old days, if you ever need to target super slow devices with web tech this sort of optimisation is still needed. I've used Spritesmith (https://www.npmjs.com/package/spritesmith) to good effect, there are probably others too.
It's too bad ad tracking networks ruined shared JS hosting and CDNs for everyone. There's no cache benefit to it any more because browsers stopped sharing caches between sites for privacy reasons.

(As Deno shows, ESM imports make a lot of sense from CDN-like URLs again. It just won't perform well in the browser because there is no shared cache benefit.)

The original Space Jam (1996) site does this for navigation (and it still works fine): https://www.spacejam.com/1996/cmp/jamcentral/jamcentralframe...
I just checked, and no it doesn't. The icons in the navigation are separate .gif files.

edit to add: And this makes a large part of the load time (when not cached). Other than that, the largest part is the SSL handshake and the fact that the server seems to be a bit slow (WRT the fact that it serves static content; 200ms for dynamic stuff would be okay).

Still a lot faster than most of todays websites.

In fairness I would be completely not surprised to find out it's on the same hardware as the day it launched, and probably hosts a pile of other static sites besides.
About bundling assets I'm not convinced. I've run a year-long test where 50% of our users would download a single JS bundle, and the others would use about a dozen distinct files. All using HTTP/2. I've checked every metric I could think of to see what's best. In the end the not-bundled pages would be a tiny bit quicker to load, but I the few milliseconds of difference was not significant. So I stopped bothering and do not bundle my JS anymore.
> But I've noticed most sites don't do this.

Because the trend went from having Webpack produce a 5+MB single JS bundle to splitting based on the exact chunks of code that the current React view needs, particularly to improve the experience of mobile users.

Obviously I'm not using enough JavaScript :) My typical size is well under a meg - around 300K compressed. that's for all the script for the whole site...

Cheers Bruce

We're now supposed to optimize for First Contentful Paint metric which benefits from tiny initial requests (ideally inlined css/js) rather than giant bundled js/css files
You dropped the API calls bit.

As it stands your site has to go through a TCP handshake then send the request and get the start of the response - at minimum that's 2 round trips. It then gets the JS and CSS tags in the head of the HTML and has to request those - let's assume HTTP/2 so that's another single RT of latency (on HTTP it's at least two depending on if you queue requests or send in parallel).

On 215ms RT latency that is an absolute minimum of 645ms before your JS has even started to be parsed. For a large bundle with a load of vendor code at the top in practice were talking several seconds to getting to the code that makes the API calls to get the content needed to render the first page.

And this is before we talk about any Auth, images, opening a websocket or two and people using microservices as an excuse to require a request for nearly every field on the page... (Or worse multiple requests and applying some logic to them...).

There is a fundamental minimum RT bound to a static JS based web app that is a multiple of a server rendered page. If you cache the HTML and JS bundle it can be worth it but you still need to aggregate data sources for the page on a backend and/or host it in multiple regions.

Modules are widely supported now for js which means you could have 100 modules = 100 files instead of 1 bundle of 100 modules = 1 file, obviously this is not "the most ideal" but it allows you to skip a build step. There are also frameworks like Astro that splits your pages into tiny pieces so there are definitely some ways to add a lot of requests
>If your app has to make 40 requests pulling in js files, CSS files fonts, API calls etc. to show something useful that will be visibly slow

To put this in a way the common man can appreciate, imagine you're at a restaurant and you ordered some clam chowder and your waiter brings it to you.

If the waiter brings you the chowder complete in one bowl, you get the chowder then and there. That is HN and most websites from ye olde Web 1.0 days.

Waiter: "Your clam chowder, sir."

You: "Thanks!"

If the waiter brings you the chowder piece by piece, spoon by spoon on the other hand...

Waiter: "Your bowl, sir."

You: "I thought I ordered clam chowder?"

Waiter: "Your clam, sir."

You: "Uhh--"

Waiter: "Another clam, sir."

You: "What are yo--"

Waiter: "Some soup, sir."

You: "..."

Waiter: "An onion, sir."

Waiter: "Another clam, sir."

Waiter: "A potato, sir."

Waiter: "Another onion, sir."

Waiter: "Some more soup, sir."

<An eternity later...>

Waiter: "And your spoon, sir."

You: "What the fuck."

If the waiter prioritized the spoon request, you could start eating a lot sooner.
as the content within the bowl move around as it continues to load
Oh, then we could write a new framework, for optimizing the load order, so people can at least enjoy some banner, while they wait for the real meal.
“RE:RE:RE:RE:RE:RE:RE:CHECK THIS OUT ABOUT MODERN WEB DEV LOL!”
HTTP/2 supports request multiplexing so you don’t need multiple connections or queuing to fetch multiple resources.

The bigger issue is that a lot of requests are dependent on previous requests so all the latency adds up. E.g. when you fetch Reddit, it only downloads the JavaScript and then fetches the post content. The move away from server rendering of webpages has really made things slower.

Multiplexing isn't a golden bullet. You still hit limits.

The initial TCP window is usually around 4KB so you have the handshake SYN RT (+ another two for TLS) followed by at most 4KB of request data. Cookies, auth headers etc. can make that a relatively low number of requests before you need to wait for the next RT. You also have the TCP window on the responses and again headers for large numbers of requests eat into that.

And then as you say dependencies - load the HTML to load the CSS and JS to Auth the user to make the API calls (sometimes with their own dependency chains)...

> You can reuse the connection but that means queuing requests and hitting the latency as a multiplier.

This is partially true. HTTP/2 is capable of issuing multiple requests on a single connection and retrieving multiple responses in a single packet (assuming it fits of course). So while you probably won't get the same benefit as you would with multiple parallel connections, the overhead is likely to be much less than just a simple multiple of the latency. This is especially true if you have a large number of small assets.

From my comment.

> HTTP/2 reduces the problem with multiplexing but it still doesn't go away

Even multiplexed you hit initial TCP window limits + all the response header overhead.

And many cases you have dependencies - need the first HTML content to issue the JS request to issue the Auth request to issue the API call to issue the dependent API call...

That's exactly GP's point, right? No matter us-east-1 or not, what makes things slow has nothing to do with DC location. That latency is insignificant.
HN takes - when fully cached, where it only takes 1 request - ~200ms to load, so 3/4ths of the pageload is just the roundtrip.

HN user experience in EU is "meh" because HN is one of the fastest loading dynamic pages on the web to load, meant to give you whiplash from the load speed.

Not all pages can load with 1 request, even when designed well, so they will be sub-"meh". HN, if hosted in EU, would have gotten a "daaang" rating.

> HN user experience in EU is "meh"

It's not: it's super quick, the fastest website I check on a daily basis, by very far. If only all the web could be like this!

Which is user tekmol 's point: "Hacker News is one of the most responsive websites I know. And it is run on a single server somewhere in the USA. While I am in Europe."

HN is great in the EU. If most of the pageloading is just the roundtrip, you've already won, no matter if your users are on the same continent as your unique server or not.

I disagree, but that does not matter - even if you think it is fast somewhere in the EU, the fact still holds that your perceived loading time is in the ballpark of 2-3x longer than it would have been if hosted within the EU.

How you grade those experiences is subjective. Your "great" is likely my "meh", as physics dictate that we see similar results.

I'm on another hemisphere, diff continent (Africa) and closeish to the south pole. And even for me HN is very fast.
I think you are missin the point. The typical website is so bloated that a latency of a single roundtrip is not the root cause. They may load quicker if roundtrips are faster, but that's then mainly because they make too many roundtrips.

That it makes a significant difference for HN (as in: "measurable") is because HN is so snappy in the first place.

Apart from that, being located in Europe, I agree with the other posters that claiming HN being "meh" in Europe is just nonsense. It's one of the quickest websites you can come across on this planet. Anywhere on the planet.

Latency of a single roundtrip is the sole reason for the bloat being an issue. The bandwidth requirements to load even the heaviest webpages at a few megabytes is negligible for most people, but these pages are slow to load even in gigabit connections exactly due to their many render-blocking round-trips chained together.
Q1: Why would round trip latency matter so much when the modern web 45.0 adds so much overhead?

Q2: Why don't we just force all the SV techbros to test their sites - AND their browsers - on a $200 notebook with eMMC storage from 2 years ago?

Because most sites aren't interested in their users who use bad hardware as a market share. The most attractive client base are the ones with money to spend.
Rich people tend to be old, and not all, but many old people have bad hardware, even if they are rich. Meanwhile, 87% of US teenagers have iPhones.
Fair point, but even high end users have bad connection sometimes.
It matters a lot. I just spent three days on a 130kbps 1000+ms latency high packet loss connection, and RTT was one of the problems that made lots of sites I tried (practically) unusable, due to launching dependent queries in series without any retries. The other big one was gigantic interaction-blocking assets served from CDNs with aggressive timeouts.

SV techbros are a fun pinata to smash, but that's a load of bullshit intended to conflate individual workers (easily hateable and zero power to fix anything) with ad-tech/paywalls/lead acquisition/overoptimisation driven by profit-seeking (too diffuse to hate, too little understood for lawmakers to regulate effectively...yet), and make slow websites seem like a technical or competency problem instead of an auctioning-your-eyeballs-and-spamming-you-with-modals.

Pretty sure the guilt is shared. The profit seeking personal data peddlers don't choose overengineered solutions that only make sense at google scale.

I also have a feeling hardware designers could use being forced to live somewhere that's not a dust less constant temperature air conditioned office in California, but that's another matter for a different rant.

The SV techbros should have to test their sites on 2010-era notebooks running through two VPNs connecting through Australia and Finland.