The Christmas break provides the time to tie up loose ends and make much needed progress on personal projects. At least, that was the plan. Once again I find myself distracted by the task of making this website just that little bit faster.
As a follow-up to last month’s post, here are some additional performance enhancements I’ve made between eating the left over turkey.
Fewer HTTP requests
I love the ingenuity of Aaron’s approach, not least because it builds upon a clean, semantic base, and feels like genuine progressive enhancement. That said, Opera Mini has trouble interpreting the
:target pseudo-class selector this solution uses, so it’s not without its problems.
Mashed up icons
A further request could be removed by using data URIs and encoding the SVG image sprite as a base64 string in the CSS. This became a less attractive option when I learnt that the size of this string would be larger than the linked file it would replace.
As I sought to reduce the size of the sprite, I realised many of the graphical elements it contained could be provided with simple CSS rules: the three line menu icon, the round containers for back and forward navigation links — even the Flickr icon in the footer could be generated using CSS. With these removed, the remaining icons appeared best suited to being served as a web font instead.
I now find myself using a combination of techniques. The logo continues to use SVG, but encoded as a base64 string. CSS styles are used to create simple shapes and icons, with a custom web font (created using the amazing IcoMoon app) used for more complex icons.
In order to keep the size of this file down, fallbacks (PNG for the logo, EOT and TrueType for the web font) continue to reference external files. This means users of older browsers may end up downloading both the fallback assets and the files encoded within the CSS. It’s not a perfect situation, but going by my analytics data, this won’t affect many visitors.
In addition to these changes, refactoring the remaining styles meant the new CSS file is slightly smaller than the three previous files it replaces:
|Before (CSS+JS+SVG)||11.47 kB (3)|
|After (CSS only)||10.76 kB (1)|
Improved time to first byte
In my previous post, I mentioned that I was now serving the site via CloudFlare. Beyond providing content distribution and file optimisation, this service provides a layer of protection from security threats like SQL injection and denial of service attacks.
I really like CloudFlare, but it came with a notable downside: Time to First Byte times were longer than they ought to be. This issue has been dismissed by CloudFlare, yet real world usage suggested the responsiveness of this site was indeed impacted. Andy Hume recommended I try Fastly. While it doesn’t optimise files or provide security protection, it provides the same core service as CloudFlare more effectively1:
|First byte||1,225 ms|
|Document complete||6,722 ms|
|Fully loaded||6,798 ms|
|First byte||189 ms|
|Document complete||2,988 ms|
|Fully loaded||3,064 ms|
|First byte||1,188 ms|
|Document complete||1,961 ms|
|Fully loaded||3,445 ms|
|First byte||387 ms|
|Document complete||743 ms|
|Fully loaded||743 ms|
By moving away from CloudFlare, the site now loads twice as fast. On repeated views the response is four times faster, although that figure is also helped by the optimisations I described earlier, and by the fact that I’m now caching my PHP files.
If a single lesson is to be taken from all this, it’s that often the biggest gains can come from the simplest changes. If you’re interested in improving the speed of your own website, start with the bigger pieces on your plate first.
I dare say further improvements could be made, and I wouldn’t be surprised if I’m writing a similar blog post again soon.