26th March 2022

Accelerating Page Load Times by Reducing Requests, Part #2

In continuation of Accelerating Page Load Times by Reducing Requests from last year, I tried to reduce the number of request even further. This time I stumbled on this opportunity by accident. When I changed my favicon.ico file, I read at favicon.cc that you can embed your favicon.ico between the <head> HTML elements in base64-encoded form.

This inline embedding of images is called data URI scheme. It is analogous to here documents.

1. Inlining images. To start, I measured with tools.pingdom.com to have a baseline. I tested the page Index for Year 2013, which mostly contains just text. The tests were conducted with "Europe - Germany - Frankfurt" server location. Performance grade was A97 with 7 requests, page size was 17.4 KB.

Next I changed the favicon.ico with embedded base64-encoded image on same page:

<head>
    <link href="data:image/x-icon;base64,AAABAAEA(...)AAAAAAAA" rel="icon" type="image/x-icon"/>

Performance grade was still A97, but only 6 requests as expected, page size dropped to 14.8 KB. This drop in size initially came as a surprise. But it is obvious as each request transfers HTTP header information in request and reply. Just leaving out this single request reduces the size.

Further analyzing how the remaining 6 requests were contributing to the performance grade A97.

Clearly, I was on the right track. So I replaced all small images, which are part of the menu, with inlined base64-encoded images. Previously, I had below code in my header template PHP file:

<a href=<?= $rbase ?>/blog>Blog</a>
<a href=<?= $rbase ?>/music>Music</a>
<a href=<?= $rbase ?>/aux/about>About</a>
<a href=<?= $rbase ?>/aux/search.php><img src=/img/Actions-file-find-icon.png height=32 width=32 alt=Search></a>
<a href=<?= $rbase ?>/aux/yearOverview><img src=calendar-icon.png height=32 width=32 alt="Year Overview"></a>
<a href=<?= $rbase ?>/sitemap.html><img src=file-icon.png height=32 width=32 alt=Sitemap></a>
<a href=<?= $rbase ?>/feed.xml><img src=rss-icon32.png height=32 width=32 alt="RSS Feed"></a>

I replaced all /img/* images with their corresponding base64-encoded form by using:

base64 -w0 rss-icon32.png

With that gibberish I replaced the images to:

<a href=<?= $rbase ?>/blog>Blog</a>
<a href=<?= $rbase ?>/music>Music</a>
<a href=<?= $rbase ?>/aux/about>About</a>
<a href=<?= $rbase ?>/aux/search.php><img src="data:image/png;base64,/Zeu4(...)UVORK5CYII=" height=32 width=32 alt=Search></a>
<a href=<?= $rbase ?>/aux/yearOverview><img src="data:image/png;base64,d8CAR(...)lFTkSuQmCC" height=32 width=32 alt="Year Overview"></a>
<a href=<?= $rbase ?>/sitemap.html><img src="data:image/png;base64,mvQIixj(...)lFTkSuQmCC" height=32 width=32 alt=Sitemap></a>
<a href=<?= $rbase ?>/feed.xml><img src="data:image/png;base64,ezrUMx(...)lFTkSuQmCC" height=32 width=32 alt="RSS Feed"></a>

To really get rid of all further requests to small files, I also inlined the CSS. The CSS file was previously in jscss/blogklm.css. Now it is:

<style>
(...) CSS code
</style>

Above code is between <head> and </head>. The HTML does no longer look nice and tidy, but the performance benefited. Performance grade is A100, number of requests is 1, page size dropped even more to 12.2 KB.

Below breakdown of the download time shows that the actual download in green is a very small percentage of the overall networking time, which consists of DNS lookup, SSL handling, creating the connection, sending the actual request, waiting for the reply of the web-server over the network, then actually receiving data. This ratio is 3.8/240.3, i.e., roughly 1%. This justifies that making the web-site larger can actually drastically decrease overall load time, when you keep the required number of requests low.

2. Comparing to previous results. The blog post Moved Blog To eklausmeier.goip.de is a small post, containing only text. In Speed-Tests With Pingdom.com I measured performance grade B87, page size 332.9 KB, load time 1.06s, and 18 requests from Washington D.C. At that time, May 2021, I used Tailwind CSS. Now the results are performance grade A100, page size 9.3 KB, load time 681ms, number of requests 1, also serving Washington D.C.

For the blog post Simplified Saaze I measured performance grade C80, page size 54.5 KB, load time 1.67s, and 33 requests in November 2021. I tested for Washington D.C. and used unpkg.com for prism.js. See Accelerating Page Load Times by Reducing Requests. When serving prism.js locally and combining into a single JavaScript file, performance grade improved to A93, page size shrank to 44.2 KB, load time decreased to 947ms using 9 requests. All from Washington D.C.

Now with image inlining performance grade further improved to A99, page size dropped to 39.9, load time shrank further to 886ms using 3 requests.

Breakdown of those 3 requests is as below.

Keep in mind that I serve those web-pages from my tiny server in my living room, no CDN, no enterprise cloud.