Optimizing the website's load performance

Date

Tags
#selfhosting

My old webhosting

When I started making websites back in 2010-ish (maybe even earlier than that, I don't remember), I used shared hosting as I did not have the slightest clue about how a server worked, let alone set one up for web hosting. About two-three years ago, I switched to Cloudways, allowing one to host websites on a virtual private server (VPS) and still not require any actual knowledge about the inner workings of a server.

My new webhosting

However, I've been managing my own private server for almost two years so I felt confident I could do the hosting myself. Hip as I am (I am not), I decided to go with a Caddy server as a Docker container on a VPS hosted by DigitalOcean. For the low-traffic websites I currently maintain, this is largely sufficient.

I am in the process of moving each website one by one to the new hosting solution. It was time for this very website, yarmo.eu and I thought to myself:

I should actually check if I gain any website load performance by moving to this new solution.

When asking the Fediverse, 70% predicted Caddy would perform better than Cloudways.

Let's get testing

I decided to use WebPageTest.org to measure load perfomance. For each case described below, three measurements were performed and the median measurement is displayed and analyzed.

Cloudways

First, a baseline measurement of my existing Cloudways solution.

Cloudways - overview
Cloudways - overview

Cloudways - rating
Cloudways - rating

Cloudways - waterfall
Cloudways - waterfall

So the server returns the first byte of information after 480 milliseconds. Now, I should tell you that my website is based on Phug, the PHP port of pug.js templating. The page is rendered in real-time and apparently, that takes a little over 300 ms.

It is worth noting that any other metric is then dependent on how the website is programmed. Once Cloudways has sent over the data, it no longer has any influence on load performance.

The website if fully loaded after 923 ms. Good to know. About a second to wait for my website to load.

Over on the waterfall, we see a bunch of files being downloaded simultaneously after the HTML page is loaded. The largest asset to load is the profile picture.

Wait, what is that F over on the rating? Security is NOT in order! As it turns out, Cloudways does not handle security-related HTTP headers for you… I did not know that! They recommend setting these headers in a .htaccess file.

Let this be a reminder to all of you: test your websites. One might learn a few tricks.

Anyway, can Caddy do better?

Caddy

Caddy - overview
Caddy - overview

Caddy - rating
Caddy - rating

Caddy - waterfall
Caddy - waterfall

Well, as it turns out, it's largely the same performance. First byte arrived after 459 ms, but I've ran it a few times and there's really little difference between Cloudways and Caddy.

BUT! Learning from my previous mistakes, I configured Caddy to set up all the correct headers and won't you look at that, A+ on the security score!

So that's it then?

Well, not really… I learned that my website wasn't running optimally because I forgot some basic HTTP headers. Did I forget more? In other words, can I do even better than this?

I've tried a lot of things, I'll just narrow it down to the two most important findings.

Caddy - inline most of it

As it turned out, I had a few small SVG icons and some CSS files. I tried rendering them into the HTML page, so the data would be sent on the first data transmission and no separate requests were needed. For good measure, I also minified the CSS files which, for one file, reduced the size by 30%!

Caddy+inline - overview
Caddy+inline - overview

Caddy+inline - rating
Caddy+inline - rating

Caddy+inline - waterfall
Caddy+inline - waterfall

On the waterfall above, you can clearly see the dank-mono.css was not inlined but I tried multiple configurations, there was no real gain as the image also needed to load and took longer anyway. So, all in all, inlining the SVG and CSS content did little in this case.

Also, note the regression from A+ to A on the security score. There was one header I couldn't quite get working properly so I had to disable that one, other than that, it's working better than it ever has.

What drew my attention for the final step was the B. My server responds in within 480 ms and that it still not good enough for you, WebPageTest? Ok, have it your way.

What takes my server so long to respond? Well, obviously, it must be the templating. Can I improve the template? Perhaps. But as it turns out, I don't have to! Ever heard of caching?

As described on their website, PHUG has support for caching and even calling an optimized version of their renderer. So I applied both caching and optimized rendering.

Caddy - PHUG optimization

Caddy+PHUG - overview
Caddy+PHUG - overview

Caddy+PHUG - rating
Caddy+PHUG - rating

Caddy+PHUG - waterfall
Caddy+PHUG - waterfall

Well, there it is!!! First byte of data arrived after a mere 173 ms, website is useable in less than half a second and all scores are A!

That's the result I was hoping for. Now on my todo list:

Any comments or recommendations/optimization? Please let me know!