Getting this Blog to Score 100 on Google PageSpeed Insights

Mar 30, 2020 — 4 mins read

This blog has gone through so many changes that it's tough to detail a specific roadmap. It started as a static site with no blog and then had a blog added using Jekyll. I didn't like Jekyll, and found WordPress to be too bloated. Eventually I built the first basic version of this blog with Laravel, and used prismic.io as a headless CMS. Despite it being very simple to integrate, I didn't like Prismic, and decided that already having Laravel meant I could build something myself. Eventually I found cnvs.io, and after a couple iterations I'm finally happy with what I have.

It's pretty obvious I enjoy building blogs more than actually adding content to them!

What I also enjoy more than writing is optimizing this blog for speed. For a while my PageSpeed was in the low 90's and I knew that multiple blog iterations left bloated code that I could better optimize. Below are the main things I optimized to achieve a perfect PageSpeed score on the desktop test and consistent high 90 scores for mobile.

Update (April 3rd, 2020): Since switching to Tailwind, the desktop score fluctuates between a 99 and a 100 score. More optimizations coming soon! 😁

Hosting

I started with where I host my blog. I've been using Cloudways for hosting Laravel for years, and even though they wouldn't be my first choice now due to better tools being available, I'm locked in now. I made sure my DigitalOcean Droplet had the resources available to handle more traffic, and I ended up upgrading to a better Droplet. The cheapest Droplet will have no issues serving a basic Laravel project, but will start to have issues when you host multiple apps.

Cloudways has built in caching and Redis support which I use to keep my sites fast, and this will get you a long way on the PageSpeed Insights.

I would love to migrate my projects to serverless with Laravel Vapor, but as of right now I just can't justify that for the amount of traffic I get. One day!

Queries

The next point of potential slow down is after getting routed to a controller and having your queries be slow. In my case, my queries were already optimized with Eager Loading. I always try to limit individual database queries (avoiding N + 1 problems) and is therefore my queries are performant. In the case of my individual post query (seen here), there is only one query being made and the rest of the method formats data using collections.

The next improvement I could do to mitigate any slow downs due to traffic spikes would be to cache posts for a short period of time to limit the number of identical queries being made. I have integrated Redis already so it'll be easy to start caching that data but for now it's not necessary.

Images

In the case of this blog, there are very few images and the images that are included are small. I made sure to optimize the images that are displayed on all pages of this blog, and if possible to include icons in the SVG format.

CSS/JS

After multiple revisions of this blog, there was a lot of useless CSS and JS just hanging out and costing me load time. I removed the fluff that was no longer necessary and used Laravel Mix to compile assets and minify the files for productions. I was really happy with how easy it was to do, and it made an improvement.

Update: I have now rebuilt the frontend with Tailwind as a replacement for Bootstrap. I really enjoy using Tailwind, but it has cost me a very small bit of performance. I'm confident I can optimize further though!

The next step down the line will be to limit the CSS to load after the page content has loaded. This of course will make the site flash on the screen un-styled for a split second, and that can be quite jarring. The solution to this is to only send out the CSS needed to style content above the fold of the browser. This is tough to do for me because of how simple the blog is (pretty much the same style the whole way down the page), but maybe down the line I will do this.

Tip: Check Chrome Network Tab

After a bunch of changes there were still resources loading slowly according to the PageSpeed test, so I opened up Chrome's Dev Tools and went to the Network Tab. This showed me what resources are taking forever to load, and in my case it was my Font Awesome Icons JS script! I decided that since I only show the icons in the footer and they are always the same icons, I would just find SVG versions of the icons and use those to omit using the script altogether.

Conclusion

This blog is extremely simple which makes it easy to optimize, but it's been a great exercise to learn optimization techniques. In the future I'll use caching and some clever CSS tricks to further bring down load times. One day I might also deploy to AWS (serverless), and that will also bring improvements. My next step in the near future will be to integrate a better CDN to load images, and further reduce load from my Droplet.