101K 9 Dec 18:30 with.css
99K 9 Dec 18:31 with.min.css
73K 9 Dec 18:31 with.min.css.gz
6.8K 9 Dec 18:30 without.css
5.2K 9 Dec 18:31 without.min.css
1.8K 9 Dec 18:31 without.min.css.gz
> …72k, which is not much bigger than the CSS without the fonts + the fonts separately.
The issue here is that CSS is a render-blocking resource and fonts are not; ergo you’ve increased render-blocking assets from 1.8K to 73K, meaning the user has to download 4056% more bytes before they get to see anything at all. Base64 encoding assets is usually a huge anti-pattern. You’d be better off moving those fonts back out into separate requests.
I hope this comment is taken in the spirit it’s intended: I like making the internet fast :)
Have a great weekend!
(If you’re interested in further reading, look up anything to do with the critical rendering path.)
One advantage of embedding the fonts is that it eliminates FOUT. If the fonts were split out, once the fonts were loaded, the page would need to be re-rendered anyway. I don't see much practicality of rendering an already light page if it's going to be re-rendered differently quickly after.
By embedding the fonts, I've optimized for latency in downloading fewer files over HTTP1. Even a 2k CSS and 20k-ish font are hardly worth the cost in opening the connections; a 73k all-in-one is more efficent. Let's assume a reasonable 8mbit connection and 50ms RTT.
To download the 72k CSS on a new connection (because it's early in the page load), that takes 100ms to establish TCP and HTTPS handshake, and 122ms to download the 72k embedded font CSS, total: 222ms (at least, not including processing overhead).
For the split version: 100ms for handshakes, and 52ms for the 2k CSS transfer. Here, the browser might keep it open to download one (the headline font) (negligible load time for a open connection), and open another connection for the body text font. (the third monospaced font is rarely used.) The open one would download one 23k font in 73ms. The other connection (in parallel) will take 100ms for handshake, and 73ms for another 23k font. total: 325ms (at least, not including processing overhead).
For higher bandwidth connections, bigger files make even more sense. For split files to truly win, latency will need to be impossibly low, which for the hosting from my apartment basement (even on 150mbit fiber), is impossible.
Even though it's render blocking, browsers will continue loading other assets anyway. A mostly (if not fully complete) page will show the first time, often within a second on wired connections.
> I hope this comment is taken in the spirit it’s intended: I like making the internet fast :)
Yup. Me too!
> Let's assume a reasonable 8mbit connection and 50ms RTT.
This is a huge assumption; you’ll be neglecting almost all of your mobile users there. But! Optimise for your use-case, of course.
If you’re self hosting your fonts I would leave them external, `preload` them, and use the preferred `font-display` mechanism to deal with (or elimiante) FOUT and/or FOIT. That’s your extra connections taken care of, and we’ve moved fonts back off of the critical path :)
I think what we’ve both hit upon here is the fact that browsers need to decide on a standard way of handling FOUT/FOIT. Leaving pages blank for up to 3s (or in Safari’s case, indefinitely) would completely eliminate the need to try and circumvent it by base64 inlining :(