Honey, I shrunk the blog!

At the time of writing this post, loading the front page of this blog without anything cached takes around 1MB of data. Compared to the average website page (according to the http archive), this is actually pretty good. The median page apparently ranks in at around 2MB of data, with about 1MB of that being images, and another half a megabyte of JavaScript. Even worse, according to the http archive's 2019 page weight reports, 10% of website pages are over 6MB, resulting in requiring at least a second to load the page on many internet connections around the world.

Obviously this blog is no where near as bad, so why have I taken this entry to talk about page size and how I've made this blog smaller? (Yes that's the topic if you haven't picked it up already.) Well this blog is almost entirely text, with one image that is used for the header/footer, and some custom fonts. There is no JavaScript, no videos, some CSS (although not that much locally, only 9KB is CSS that is hosted here), so why on earth is this website checking in at even half of what the "normal" website would be?

Well the answer, as it turns out, is entirely that one image that is used for the header and footer of the website. The profile image (which I use as my profile picture in most places) is a 2320x2314 JPEG image that takes up 747.8 KB of space. That's an absolutely whopping three quarters of my entire page, for one image that arguably isn't even needed. Fortunately, there's ways around this.

The container that my image sits in at the top of my page is a square with a side length of 125 pixels, so this image only actually has to be 125x125 for there to be no noticable change in quality from the original. The container at the bottom of the page is also a square with a side length of 30 pixel, and as 30 is not a divisor of 125 it makes sense to create an image for that separately so that the image doesn't sub-sample oddly.

The static site generator that I use is called Zola, and has a number of inbuilt functions in its templating. One such function is the (very handy) resize_image function, which (as you'd expect) resizes an image to be of some particular dimensions. The function processes an image for you and returns its path, allowing you to keep almost everything unchanged save the loaded image url.

-      <a href="{{config.base_url}}" style="background-image: url({{config.base_url}}/img/{{config.extra.profile}}"></a>
+      <a href="{{config.base_url}}" style="background-image: url({{resize_image(path='../static/img/' ~ config.extra.profile, height=125, width=125, op='fill')}}"></a>

By applying this function, I ended up with images of sizes 4.15KB and 1.21KB for the 125x125 and 30x30 images respectively, a total reduction of 742.4KB. That's basically a saving of the size of the entire original image, with no discernible change in image quality!

Of course, after this change I was greedy for more gains, and thus began my fight for fonts.

I use a number of fonts on this blog (and on my main website), which are generally downloaded from Google Fonts on demand via CSS. Raleway is used for the text of front matter (the information for each blog post such as the publishing date, total words and tags), whilst the excellent Montserrat is used for the rest of the text elsewhere. Whilst I have replaced my Raleway with a combination of Verdana and Geneva, Montserrat will be sticking around as (in my opinion) one of the best looking variable weight sans-serif fonts available. Thus, my savings with actual fonts was only around 20KB, relatively paltry gains.

 html, body {
     background-color: $background;
-    font-family: 'Montserrat', 'Raleway', sans-serif;
+    font-family: 'Montserrat', 'Verdana', 'Geneva', sans-serif;
     font-weight: 400;
 }
 .frontmatter {
     color: $title;
     font-style: bold;
     list-style-type: none;
     font-size: 14px;
-    font-weight: 700;
-    font-family: 'Raleway', sans-serif;
+    font-weight: 500;
+    font-family: 'Verdana', 'Geneva', sans-serif;

My major gains in the fonts department actually came from another place entirely... FontAwesome. FontAwesome is a fantastic font for using company logos instead of images, which does indeed save a lot of data compared to the size that even one image of a logo would be. The only problem is that the entire stack of FontAwesome icons that I'd need to get for my little symbols next to my website, GitHub and Atom feeds is around 130KB, which (now that we've shrunk a large portion of the website) accounts for about half of the remaining website. Fortunately for me, FontAwesome provides SVGs of their icons, which allows me to download them all individually and use them instead in <img> tags. The total size for the three icons individually is a little under 5KB, around 25 times smaller than the entire font.

-  <li><a href="https://{{extra.website}}" target="_blank">website <i class="fab fa-firefox" ></i></a></li>
+  <li><a href="https://{{extra.website}}" target="_blank">website <img class="symbol" src="/symbols/firefox-browser-brands.svg"></img></a></li>

According to Firefox's network tools, I'm now down to 128.2KB, of which my remaining font of Montserrat makes up a solid 70%, so there's clearly still some room for improvement. Perhaps I'll continue to look for an alternative font to use instead.