Making Websites Small
santurcesoftware.com
santurcesoftware.com
- Reducing DNS calls and server round trips. Loading fewer resources from fewer domains makes a huge difference. Using server push also helps, although it might get deprecated.
- Responsive images. Load small images on small displays. Don't load 2x images on lower density displays.
- Using the right load event for JavaScript. load fires long after DOMContentLoaded on some pages, especially on slow connections.
- Setting the size of elements before they load, to prevent the content from jumping all over the place.
- Loading fewer fonts, and serving them yourself. Google Fonts is significantly slower.
- Gzipping everything you send. It makes a significant difference on slow connections.
- Static caching. This will shave whole seconds off your page load time. Cache both on the server and in the browser, but mostly on the server.
- Consider perceived performance too. It doesn't matter how fast you force a coercive cookie notice on your readers.
- Performance extends to the content of the page. Don't make users chase answers. Give clear, concise information and use typography to guide your users to it.
This is especially jarring on a phone. Multiple times a day, I see this, and it pisses me off each and every time. Nothing like reading an article to all of a sudden have some image load somewhere (likely not even visible on screen) suddenly cause what you're reading to disappear off screen. And I'm not on a slow connection, either. I'm typically on uncongested wifi connected to fiber when at home, 5G otherwise.
JavaScript in general is so bad, or rather is being used for so many bad practices, that I've disabled it on my main mobile browser. What little good it's used for doesn't out weigh all of the bad out there. I'm tired of malicious ads hijacking the page, either rendering popups or redirecting me somewhere I don't want to go. If a site doesn't render anything useful without javascript (Twitter is a prime example), I typically turn around and go elsewhere.
https://www.smashingmagazine.com/2020/03/setting-height-widt...
https://christianheilmann.com/2021/04/14/quick-vs-code-tip-a...
There are extensions (Dark Reader, a dark/light mode extension for Firefox, is an example) which trigger multiple redraws of a page on load. On an e-ink device (my principle driver these days), the extension is a near necessity (ironically, to force black-on-white themes on sites, much more readable on e-ink), and page re-paints are all the more jarring and expensive.
Simple pages still load quickly and without disruption. Many complex sites don't. (NPR's website comes particularly to mind.)
This is the worst on picture rich recipe blogs. I hate it.
Responsive images are kind of funny in the sense that my webpages are nearly twice the size on mobile vs my laptop. The screen may be smaller, but the CSS pixel ratio is 1 on my laptop vs 3 on an iPhone.
Perhaps writing things by hand has a questionable nostalgic allure of "keeping one honest" but beyond that I don't think it's super practical.
An unoptimized payload isn't that big of a deal if it's still smaller than the best optimized one.
Edit: This is an even better example: https://medium.com/general_knowledge/top-10-crypto-gaming-pr... How anyone can look at that image and say "that'd be perfect for the top of my next post" is beyond me.
I'd rather have a half-loaded page with images/fonts missing than a JS-based page which won't give me anything until the full JS payload is downloaded & executed.
I’m looking at Astro for my site’s re-write as it seems to find a happy medium here.
Sounds like WebComponents.
>I'm looking at Astro...
Never heard of it and just gave it a quick glance. Hadn't heard of the "islands architecture" it implements either, although it is similar to some familiar concepts.
In fact, it reminds me of the way we built sites years ago (pre-AJAX even), when static HTML was just delivered by the server and there was little-to-no JS involved, save for some effects.
And, that's the funny thing: in spite of all the myriad paths and paradigms, we seem to be coming full circle. It's funny in 2021 to see a "new" project advocating for a "new" approach that is essentially "SSR static HTML with minimal client JS FTW!"
Interesting. I’ll check it out.
Update: checked it out. Shame that `Getting Started` > `Web Components` = 404.
WebComponents have been discussed for a while. They were just a dream not too long ago, and I'm not sure what their usability is right now. So, word of warning that I'm not advocating for or against their use at this point. Just mentioning that the description you gave previously reminded me of WebComponents.
If you work on bigger projects you will run into many problems really soon. Like some Safari strangeness when it comes to CSS. Someone using some old browser which you as a developer would never use but your user base still uses it and it makes 12 % of the revenue.
No, it does not help. CSS is trivially small, especially after it's compressed. Same for HTML and JS. JS will balloon in size if you start using Webpack, but your own code will stay fairly small.
A single image will outweigh your text files, so the effort isn't really worth it.
plus careful image scale, quality and progressive display. Often images appear to be print quality. You need to know about the difference of web and print, however.
Is there any chance in the future that browsers are going to support / implement lazy-loading of images themselves (i.e. based off what's visible in the viewport). Currently you have to (as far as I'm aware anyway, but I'm only just getting re-acquainted with web-dev) use JS to do it (things like LazySizes), which adds complexity, and is even more complicated if you want to combine that with responsive images...
Or am I missing something that's possible already?
I host a personal photo gallery online and I've been dreading implementing this for images to get rid of the jump when lazy loading. I'm not even sure there's a good way to do it.
It’s kind of a hack, but it lets me compute the final image flow based on the file name before any of the images have loaded.
This is off the top of my head but if your images are set to a percent based width so they scale (mine are) and you know the aspect ratio of the image then you can set the CSS ‘ aspect-ratio’ property (or there are some other hacks with padding on a wrapper div) to maintain the height.
You’d probably want to integrate this into the build process but I have not done this.
https://www.smashingmagazine.com/2020/03/setting-height-widt...
https://developer.mozilla.org/en-US/docs/Web/CSS/aspect-rati...
Using a css flexbox or grid layout means you don't have to recalculate image div widths and heights when the browser viewport width changes, but you still need to give it enough information to back into the correct aspect ratio.
Also, using a srcset helps only load the necessary bytes, but means you'll need to either build the resized image on the fly (which is cpu-expensive) or prebuild them (which takes up some disk space).
In the interests of a performant UI, PhotoStructure extracts and remembers width and height of photos and videos during imports, but if you're only loading a couple images in a gallery, your could fetch this metadata on the fly as well.
If it's another kind of gallery it could work if you accept those constraints. If you don't, then it's better to use width/height anyway.
I want to say I did something like this for an infinite scroll, grid layout some time ago where I didn't have the image dimensions to help the browser. Details are fuzzy but there seemed to be a gotcha here and there, some of which was around the load event.
Of course, the user's perceived wait time goes up a bit, as you're not displaying each image as it loads. But, that can be mitigated somewhat by fewer images per pagination and/or preloads.
The overall solution worked well for our use case.
This stuff is hard
I did check on my Android and it's similar, 1080P display but 412px wide in browser
also that bottom navbar in Safari ahh
How about no serving of fonts? I don't think I've ever looked at a webpage and thought it would be improved by a particular font family. What exactly can't be accomplished with standard web fonts? Icons? Haha, don't even go there.
Imagine if the trade-off was more explicit to the visitors: would you want something that made your web browsing slower, your text flashes in like a cheap powerpoint slide, and sent your data to Google, in exchange for being able to read in a different font? External web fonts are purely for the ego of the web developer, not for the reader.
Everything, everywhere else, seems to work just fine with using the browser defaults.
That's probably because of the Google Material Icons font, I believe? It shows or used to show text instead of icons when it couldn't load.
All icon fonts _should_ do this. It's just that the Google Translate site is designed in such a way that the fallback text doesn't render correctly, overflowing and overlapping over everything else, which makes it noticeable. It seems to very much be a 'pixel perfect' design, rather than responsive.
Everywhere else, the fallback fits naturally, or renders to a standardised UTF-8 symbol, so that it isn't noticeable to me for day-to-day usage.
Hell, I've outright just crammed a few characters into a base64 encoded font in inline CSS, which - while I'm sure makes many here grimace - loads faster than anything else I've tested.
(I'm a big fan of just shipping everything down the pipe as one file, short of images - I do this on my personal site and it makes me happy that it "just works": https://rymc.io/ )
Also, it helps with formatting code just the way I want it.
- get rid of bloated adtech (e.g. 6MB of adtech garbage from 60 domains for 20KB of text)
- remove all popups, slideovers, mailing list signup garbage, etc.
- get rid of autoloading/autoplaying video
- avoid bloated frameworks
- avoid external fonts
To reduce round-trips, consider using TCP Fast Open and 0-RTT with TLS 1.3. Note that 0-RTT can enable replay attacks, so I'd only consider using it for static content. HTTP/3 and QUIC has improved support for 0-RTT.
Gzip is good for dynamic compression, especially with zlib-ng. For static compression, I'd rather use Brotli.
Don't also forget an "Allow xyz.com to send notifications?" pop up and an overlay ad banner with a 10 seconds timeout.
Your mom-and-pop website's rank is entirely at the discretion of Google's Core Web Vitals measurements (and other SEO KPIs), but Amazon with its dumpster fire search pages with shifting layouts as content is dynamically loaded in....will be just fine.
The biggest websites in the world (Amazon, Google, Facebook, Twitter) try to push you to use their app whenever possible anyway. The web seems to be an incovenience for them, they certainly don't want you blocking any of the myriad scripts they have running under the hood to tally analytics, A/B testing, user sessions recording and whatever else.
If you have a personal website, as I do, chances are it's relatively lean, because we're the only ones designing it and keeping it updated. Chances are also that very few people visit it, because it's outranked by the thousand other bloated websites that will rank higher for whatever query it was that you typed.
So what's the point?
I understand that lots of software engineers complain about new tooling, and would rather have nothing changing, but the reality is that things will change. So we might as well fight for them to change to the better, by proving it is possible and showing/teaching others.
I also understand that people don't think FAANGs will ever fall, but just as Google disrupted every search before and Amazon disrupted brick and mortar stores, there can be something with a differentiator that will disrupt them in the future, and that differentiator might be going back to the web. Of course, there's the possibility of Google killing this new disruptive corner of the web as soon as its born, but oh well...
Integrity. As hard/cringey as it sounds it's because of integrity that the internet is still relatively free and software like firefox exists
max-width: 50em
Wikipedia has this quirk as well though, where if you have a large monitor, you can end up with ridiculously long lines that are impossible to read.I recently made a site that frontloads an entire Svelte app, every page and route, entirety of site data (120kb gzipped), all of the CSS and a font full of icons, a dozen images, service worker and manifest. Clocks in at exactly 250kb, scores 100 on LH, fully loads in 250ms uncached, and all navigation and searching is instantaneous.
That's not a brag, it just goes to show that anyone can make sites which are bandwidth and energy friendly, but for some reason very people actually do that anymore.
My latest website[0] is 7.5kb, and I built it after getting fed up with the official MotoGP no-spoilers list which sends 2mb to surface the same information in a much less user friendly way. This is how the bulk of the internet should look.
Yep. My personal site (70+ posts) is 26kb. 17kb is the syntax highlighting library.
Another project site of mine is 2mb but that's because it has a lot of screenshots. I should probably shrink those screenshots though...
The recipes section inspired me and now I need to add something similar to mine. And props for not tracking.
>1500x1750 and weighing in at 3MB! The webp version of the same size is ~79KB.
79KB is a very low 0.24 BPP ( bit per pixel ). for 1 BPP it would be 328KB.
AVIF is optimised for BPP below 1, while JPEP XL is optimised for BPP above 1. On a MacBook Pro, the first fold of the browser has 3456 x ~2200, an image filling up that screen with BPP 1 would equate to 950KB.
In a perfect would you would want JPEG XL to further optimise BPP below 1.0 and do progressive loading on all image.
We have also bumped out monitor resolution by at least 4x to Retina Standards.
Despite our broadband getting so much faster, file size reduction is still the most effective way to get a decent browser experience. At the same time we want higher quality images and beautiful layout ( CSS ) etc.
Balancing all of these is hard. I keep thinking if some of these are over optimising, when we can expect consumer internet speed to increase in the next 10 years.
YMMV but 99% the images I see on the web, I don't care about their quality. A large part of them are annoying, and most of the others could be low-resolution and low-quality, I would not even notice it, except for the faster page load. Once in a while, a photo is artistic or interesting enough to gain from a high quality, but most web sites I visit have far too many heavy images.
And, PR could definitely become a Singapore if the government would embrace that possibility (they're already part way there with the low taxes for expats), but I think they are too populist and just don't have that kind of vision for the future of the island.
Many sites are becoming practically unusable as more and more crap is loaded for not-good-enough reasons. When websites from social media to banks often take tens of seconds to load, it is obvious that the designers and coders could not care less about the UX.
Even the definition of a "small" site has grown three orders of magnitude. There used to be a 5KB website competition [0], which grew to a 10K contest. Now, the link is to a One Megabyte Club [1] list of small websites.
I don't know how to reverse the trend, but managers and coders need to realize that just because some is good, does not mean that more is better.
Edit: line breaks. Also note that GMail HTML mode is much better than the 'standard mode'.
Build pipelines don't merely concatenate a few scripts, they're meant to automate the boring parts we used to have to do by hand (like copying assets with cache-busting filenames and update matching references, set the correct image sizes, generate SRI hashes, generate sourcemaps, generate sitemaps, check the quality of pages, etc). This way you can focus on writing the application and keeping it maintainable without having to waste time remembering to use javascript hacks (like `!1` instead of `false`) to save a few bytes like we used to.
It's when people indiscriminately feed them big frameworks that things bloat, same way you won't be lightweight with a junk food diet.
Also, I'm not sure who the article is aimed at? Local lawyers are not going to read this and be able to fix their site. The owner of the web design agency that they bought the site from isn't going to read it because they moved from tech to biz. The web dev who is implementing the site already knows this, but has to knock out sites as quickly and cheaply as possible, and so this isn't something that matters.
You're certainly never going to enjoy anything like the big shrink of using gzip, optimizing images, or not importing a big library you don't need.
The one thing I'd designers to be responsible for is image resolution, since this is intrinsically tied to website layout and affects white source photos can be used where.
[1] For example, a 100% quality jpeg is perfectly fine to work with.
It affects how they look, so it's a design issue. I'd compress them all to 1% if it primarily an engineering issue.
That seems like a lot. What's going on here? Surely the compression level is changing drastically, right?
I'm curious how this file size would compare to a JPG at, say, level 85.
You can also just run an ad blocker and most of the weight goes away
If everything was coming from the same origin already, then:
• If you’re using HTTP/2 or HTTP/3 your statement is almost entirely false: whether you load in parallel or in serial, it’ll be downloading it at the same speed, except that by not inlining you’ve added at least one round trip for the client to know that it needs to request these other URLs; and now you mostly can’t control priority, whereas with everything inlined you know it’ll load everything in source order, which you can normally tweak to be pretty optimal.
• If you’re using HTTP/1, the use of multiple connections (typically up to 6) only kicks in if you’ve got plenty of stuff to download, but involves at least a couple of round trips to establish the connection, so even if using a single connection reduces the available bandwidth, it’s still normally worth it for many, probably most, sensibly-done sites.
Mind you, most web developers assume users spend a lot more time on their site than they actually do. Most visitors to your website will not click on any internal links on your page.
It's 1 big file of 100% hand-rolled html/css/js. The entire file is 1600 lines last I checked. Loads about as fast as you'd expect. I actually found a bug with the gzip threshold in AspNetCore vs chromium (the file is that small), so had to pad the index file with extra content to force gzip. Most of the dynamic UI happens over a websocket using a server-side rendering approach similar to Blazor.
We developed a quick way to view a treemap of all your pages JS (including inside bundles) from a Lighthouse report. Do it through the DevTools or from PageSpeed Insights - no need to reach for a CLI tool.
Of course, you need to have source maps accessible to see inside bundles.
Here's an example: https://googlechrome.github.io/lighthouse/treemap/?debug
Most of the site I have explore didn't appear to solve that annoyed issue as it happened to YouTube content on mobile too.
What is even more interesting is that in some parts of the world 3G is about to be phased out. Everybody on 4G and 5G?
I'm afraid not, the people who now are limited to 3G will be limited to 2G unless they invest into something new and shiny.
Sure, for some functionality you may need JS, but in like 90% of the cases JS is overused.
Please take care to read the t&Cs.
-stop using JS
-compress images
Done.