I'm not up to date on web/font development – does anybody know what that does?
So the purpose is effectively to have human-readable CSS class names to refer to given glyphs in the font, rather than having stray private use Unicode characters in the HTML?
This is a reasonable approach if you have a large number of icons across large parts of the site, but you should always compile the CSS/icon set down to only those used.
If only a few icons, and the icons are small, then inlining the SVG is a better option. But if you have too many SVGs directly embedded on the site, the page size itself will suffer.
As always with website optimization, whether something is a good option always “depends”.
Definitely a fascinating post though, there were things I’ve not encountered before.
For who? Not for 99.9% of the people clicking the link here on HN. Even regular visitors of a blog will likely no longer have things in cache for their next visit.
Pictures are pictures, text is text. <img> tag exists for a reason.
Icon fonts are used all over the place - look at the terminal nowadays. Most TUI's require an icon font to be installed.
So it's a skill issue.
Just removing the inline duplicated SVGs used for light/dark mode and using styles instead would bring it down 30%. Replacing the paths used to write text (!) with <text> and making most of the overly complicated paths into simple rect patterns would take care of the rest.
Won't be a 2.5x difference, but also not 0.001%.
Also when you get to the end, you then see
> The actual savings here are moderate: the original is 88 KiB with gzip, and the WebP one is 83 KiB with gzip. In contrast, Brotli would provide 69 KiB.
At 69 KiB you're still over the default TCP packet max, which means both cases transmit the same number of packets, one just has a bunch of extra overhead added for the extra JavaScript fetch, load, and execute.
The time saved here is going to be negligible at best anyway, but there looks to be actually negative because we're burning time without reducing the number of needed packets at all.
> At 69 KiB you're still over the default TCP packet max, which means both cases transmit the same number of packets,
What? No, they absolutely don't transmit the same number of packets. Did you mean some other word?
However, Ethernet has a MTU (Maximum Transmission Unit) of 1500 bytes. Unless jumbo frames are used.
And so I agree with you, the number of packets that will be sent for 69 KiB vs 92 KiB will likely be different.
- client requests X
- client gets X, which contains a reference to Y
- therefore client requests Y
So you're starting a new request that depends on the client having received the first one. (although upon closer inspection I think the technique described in the blog post manages to fit everything into the first response, so I'm not sure how relevant this is)If you want to learn more, pretty much any resource on TCP should explain this stuff. Here's something I wrote years ago, the background section should be pretty applicable: https://www.snellman.net/blog/archive/2017-08-19-slow-ps4-do...
- client requests X
- server sends bytes 0-2k of X
- client acknowledges bytes 0-2k of X
- server sends bytes 2k-6k of X
- client acknowledges bytes 2k-6k of X
- server sends bytes 6k-14k of X
- client acknowledges bytes 6k-14k of X
- server sends bytes 14k-30k of X
- client acknowledges bytes 14k-30k of X
- server sends bytes 30k-62k of X
- client acknowledges bytes 30k-62k of X
- server sends bytes 62k-83k of X
- client acknowledges bytes 62k-83k of X
- client has received X, which contains a reference to Y
- therefore client requests Y
It's all about TCP congestion control here. There are dozens of algorithms used to handle it, but in pretty much all cases you want to have some kind of slow buildup in order to avoid completely swamping a slower connection and having all but the first few of your packets getting dropped.Doesn’t client see reference to Y at this point? Modern browsers start parsing HTML even before they receive the whole document.
Edit: Ah, I see OP's code requests the webp separately. You can avoid the extra request if you write a self-extracting html/webp polyglot file, as is typically done in the demoscene.
Even if you transmit the js stuff inline, the op's notion of time still just ignores the fact that it takes the caller time to even ask the server for the data in the first place, and at such small sizes that time swallows the time to transmit from the user's perspective.
It is technically 2 requests, but the second one is a cache hit, in my testing.
OP is only looking at transmit size differences, which is both not the same as transmit time differences and also not what the user actually experiences when requesting the page.
The tragedy here is that while some people, such as the author of TFA, go to great lengths to get from about 100 to 50 kB, others don't think twice to send me literally tens of megabytes of images, when I just want to know when a restaurant is open – on roaming data.
Resource awareness exists, but it's unfortunately very unevenly distributed.
I wish there was a bit of an opposite option - a "don't lazy/partially load anything" for those of us on fiber watching images pop up as we scroll past them in the page that's been open for a minute.
A little OT, and I'm not sure if iOS has this ability, but I found that while I'm traveling, if I enable Data Saver on my (Android) phone, I can easily go a couple weeks using under 500MB of cellular data. (I also hop onto public wifi whenever it's available, so being in a place with lots of that is helpful.)
My partner, who has an iPhone, and couldn't find an option like that (maybe it exists; I don't think she tried very hard to find it), blew through her 5GB of free high-speed roaming data (T-Mobile; after that you get 256kbps, essentially unusable) in 5 or 6 days on that same trip.
It turns out there's so much crap going on the background, and it's all so unnecessary for the general user experience. And I bet it saves battery too. Anything that uses Google's push notifications system still works fine and gets timely notifications, as IIRC that connection is exempt from the data-saving feature.
I've thought about leaving Data Saver on all the time, even when on my home cellular network. Should probably try it and see how it goes.
But overall, yes, it would be great if website designers didn't design as if everyone is on an unmetered gigabit link with 5ms latency...
She might have kept tapping Sync at the bottom of Photos even though iOS itself pauses it when in Low Data mode. iCloud Photos and video syncing is a data killer if you're on a holiday abroad, my wife takes hundreds of photos and videos a day, imagine what it does to data.
I suppose it could make a difference on lossy networks, but I'm not sure.
These are similar conversations people have around hydration, by the by.
For the uninitiated: https://en.m.wikipedia.org/wiki/Hydration_(web_development)
> This code minifies to about 550 bytes. Together with the WebP itself, this amounts to 44 KiB. In comparison, gzip was 92 KiB, and Brotli would be 37 KiB.
But regarding the current one:
> The actual savings here are moderate: the original is 88 KiB with gzip, and the WebP one is 83 KiB with gzip. In contrast, Brotli would provide 69 KiB. Better than nothing, though.
Most of the other examples don't show dramatic (like more than factor-of-2) differences between the compression methods either. In my own local testing (on Python wheel data, which should be mostly Python source code, thus text that's full of common identifiers and keywords) I find that XZ typically outperforms gzip by about 25%, while Brotli doesn't do any better than XZ.
Also, XZ (or LZMA/LZMA2 in general) produces a smaller compressed data than Brotli with lots of free time, but is much slower than Brotli when targetting the same compression ratio. This is because LZMA/LZMA2 uses an adaptive range coder and multiple code distribution contexts, both highly contribute to the slowness when higher compression ratios are requested. Brotli only has the latter and its coding is just a bitwise Huffman coder.
So, for any reasonable connection the difference doesn’t matter; for actually gruesomely slow/unreliable connections where 50KB matters this is markedly worse. While a fun experiment, please don’t do it on your site.
1: browsers choose when to download files and run JavaScript. It is not as easy as one might think to force JavaScript to run immediately as high priority (which it needs to be when it is on critical path to painting).
2: you lose certain browser optimisations where normally many things are done in parallel. Instead you are introducing delays into critical path and those delays might not be worth the "gain".
3: Browsers do great things to start requesting files in parallel as files are detected with HTML/CSS. Removing that feature can be a poor tradeoff.
There are a few other unobvious downsides. I would never deploy anything like that to a production site without serious engineering effort to measure the costs and benefits.
Sure, if you ignore latency. In reality it's an unnecessary 0.001% increase in load time because that size increase isn't enough to matter vs the round trip time. And the time you save transmitting 55 fewer KiB is probably less than the time lost to decompression. :p
While fun, I would expect this specific scenario to actually be worse for the user experience not better. Speed will be a complete wash and compatibility will be worse.