Freddy Ewald Personal Website

Improving Page Speed

One important thing for a good user experience is a fast website. Google offers the free tool Page Speed Insights. Running it initially on my website I already have a score of 99, which is pretty good. In the past I already spent a fair amount of time optimizing the bigger problems.

Google Page Speed score of 99

I looked at the tips to improve the page speed even further. There are four things that Google considers currently in need of improvement on this page.

  • Ensure text remains visible during webfont load
  • Image elements do not have explicit width and height
  • Serve static assets with an efficient cache policy
  • First Contentful Paint (3G)

Google Page Speed recommendations to improve website speed

As a first step I made sure that the text remains visible during webfont load. It is recommended to add font-face: swap; to the @font-face CSS definition whenever a custom font is loaded that the browser has to fetch over the network. I am using the webfontloader library on my page. To change this, I had to slightly modify my Javascript code to the following. Note the &display=swap in the end.

  google: {
    families: ['PT Sans:400', 'PT Serif:400&display=swap']

After this, the largest contentful paint dropped from 3 seconds to 2.6 seconds. The score remained unchanged.

The next step was the caching of static resources. Since I am using cloudflare to serve and cache my content, it was as easy as setting the cache time to 1 year. After this, I reran the tests: Interestingly, the score for mobile dropped to 86 while the desktop score increased to 100.

The remaining issue is setting the explicit width and height for images and using next-gen formats for images. Google prefers webp. Luckily, there is a Jekyll plugin for this purpose which does a great job: jekyll_picture_tag. This gem requires vips to be installed locally as well as in the CI pipeline. I was able to do it on my Mac via brew install vips. As a CI pipeline I use bitbucket

To automatically generate different versions of the same image, I had to place the following code in my post:

{% picture jpt-webp /assets/images/page-speed-score-fewald.png --alt Google Page Speed score of 99 %}

This creates the following HTML of which the browser picks the best version to display:

  <source srcset="/generated/assets/images/page-speed-score-fewald-400-4f1148a9f.webp 400w, /generated/assets/images/page-speed-score-fewald-600-4f1148a9f.webp 600w, /generated/assets/images/page-speed-score-fewald-800-4f1148a9f.webp 800w, /generated/assets/images/page-speed-score-fewald-1000-4f1148a9f.webp 1000w" type="image/webp">
  <source srcset="/generated/assets/images/page-speed-score-fewald-400-a6c2438e5.png 400w, /generated/assets/images/page-speed-score-fewald-600-a6c2438e5.png 600w, /generated/assets/images/page-speed-score-fewald-800-a6c2438e5.png 800w, /generated/assets/images/page-speed-score-fewald-1000-a6c2438e5.png 1000w" type="image/png">
  <img src="/generated/assets/images/page-speed-score-fewald-800-a6c2438e5.png" alt="Google Page Speed score of 99" loading="lazy">

Serving webp images made the responses much smaller but didn’t have any significant effect on the score. The main issue remained still the first contentful paint. I read a tip to prefetch fonts by adding the following lines to the <head> section.

<link rel="dns-prefetch" href="//">
<link rel="preconnect" href="" crossorigin>

Finally, I added widths and heights to image tags. This is supported directly by jekyll picture tag preset. This has to be saved in _data/picture.yml, the important part here is dimension_attributes: true, which is not part of the default settings.

    formats: [webp, original]
    widths: [200, 400, 800, 1200]
    link_source: true
    dimension_attributes: true

To avoid distortion of the images I had to add CSS similar to the following:

img {
    width: 100%;
    height: auto;

With those improvements, I was able to reach a Google Page Speed 100 with only one warning. As the next step I am planning to clean up the HTML for better accessibility (currently 62) and SEO (currently around 80).

Lighthouse report showing 100 performance for

Update 2022-07-10: I read further on image formats and also enabled avif, which is an open standard and results in even smaller images. The browser now tries the images in the following order: AVIF, WebP, JPG/PNG.

I am I started this blog in late 2015, mostly as a digital business card when I bought this domain. Soon after, I started writing down observations and things that I learned during my work or free time. I am deeply interested in all aspects around software, the internet and teamwork. You can find more information about me on the about page.