Tag Archives: blogging

Perfect 100/100 PageSpeed Score With WordPress

A long time ago I worked on a theme called Elementary for my Jekyll blog. The goal was simple, to create a website that just works, and works fast. In fact, I’ll just paste the line from the readme of the GitHub repository.

This is my personal blog’s Jekyll template that I’ve been optimizing for performance, accessibility, usability, readability and simplicity in general.

I personally do not approve of personal blogs bloated with hundreds of kilobytes of trackers and analytics code, and hence, this is an attempt at creating something that I’d be comfortable with using on my website.

The goal was accomplished. I managed to get a perfect score on many of the pages. But I wanted to write more and while on the go, and plaintext editing on phones is a pain. Then the other problem was to add it to git and push it. In short, working with a static blog from an Android phone wasn’t easy.

That’s when I moved to WordPress. I ported the theme to Elementary-WordPress, which is essentially the same theme but in a WordPress shell. It worked really well, but the problem was all the bloat that WordPress sends to the frontend. For a while I didn’t care enough. I was still serving a fast website, albeit with Jquery, emojis and other code that wasn’t getting used anywhere else.

Today, that changed. I finally took some time to optimize the website and got back my perfect 100/100 PageSpeed score. Here’s how I did it.

Table of contents

  1. Disable jQuery
  2. Disable wp-embed
  3. Disable block library CSS
  4. Disable emoji
  5. Serve fonts from same domain
  6. Use font-display: optional property
  7. Use an in-memory page cache like Memcached
  8. Fix conflicting cache strategies
  9. Use a CDN for asset delivery
  10. TODO: Inline all CSS and Javascript

Disable jQuery

If your website isn’t ancient, there’s a good chance you’re not using it. If some plugin you’re using is using jQuery, consider alternatives. It will save you ~30KB and an HTTP request. Adding the following to the functions.php should do it.

function jquery_dequeue() { 
  wp_deregister_script( 'jquery' );
}
add_action( 'wp_enqueue_scripts', 'jquery_dequeue' );

Disable wp-embed

The following snippet from this answer needs to be added to functions.php

function wp_embed_dequeue() {
  wp_deregister_script( 'wp-embed' );
}
add_action( 'wp_footer', 'wp_embed_dequeue' );

Disable block library CSS

*Sigh* This goes into the functions.php

function remove_wp_block_library_css(){
  wp_dequeue_style( 'wp-block-library' );
}
add_action( 'wp_enqueue_scripts', 'remove_wp_block_library_css' );

Disable emoji

I found some nice code to disable a whole bunch of unnecessary actions from this guide here: https://kinsta.com/knowledgebase/disable-emojis-wordpress/#2-disable-emojis-in-wordpress-with-code

Serve fonts from same domain

If you’re not super keen on using the smart browser detection functionality that Google Fonts offers and are happy only supporting modern browsers, simply downloading the font files and linking them with @font-face can save an additional DNS and HTTP request.

Use font-display: optional property

I’m using font-display: optional; CSS property on my @font-face and it pushed my PageSpeed score over the top. Essentially it prevents the CLS, or Cumulative Layout Shift metric of Core Web Vitals from getting affected due to page shifting due to slow loading of font files.

Read more about it here: https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display

Use an in-memory page cache like Memcached

Building pages to serve the users is expensive as it involves the database, but isn’t something that needs to be done for every visitor visiting the same page. A plugin like W3 Total Cache coupled with a Memcached instance (could be running on the same server as the website) could enable caching of pages among other resources in memory, reducing the load on the server and improving performance for cache-hit pages.

memcached

Fix conflicting cache strategies

I’m using W3 Total Cache plugin that helps minify and cache CSS and JS files. But I wasn’t seeing any minification happening. Upon some reading, it turns out that CloudFlare’s minification conflicts with W3 Total Cache’s. Disabling it on CloudFlare’s side fixed the non-minification problem for me.

Use a CDN for asset delivery

Once the thing to deliver is optimized, it is a good idea to optimize the delivery pipeline as well. Since my server is in the same country as me, it is easy to make a mistake of thinking every visitor of the website is seeing a 50 milliseconds time to connect to the server. The further the user is from the origin server, the longer it could take.

Hence, an global CDN like CloudFlare should be used which can serve static content from its edge node physically closest to the visitor.

TODO: Inline all CSS and Javascript

It doesn’t go beyond 100, but I’d still like to improve it further. For one, the little bit of CSS and JS that does exist doesn’t have to need two additional HTTP requests. Inlining that bit will mean that blog posts without an image, which for me are most of them, will get served in only three HTTP requests; the document, the font file and the favicon. Pretty cool, huh?

Conclusion

I’m pretty pumped about the 100/100 score. WordPress has a reputation for being slow and bloated, but with some simple optimizations, it starts performing like how you’d expect some text on a page to perform like.

Thank you for reading!

Guide To A Sane WordPress Workflow

Like most things in life, WordPress isn’t perfect. But for a publishing platform, it is quite up there with the best in the business. For writing, I haven’t had any complaints so far, but when it came to customization or workflows around maintaining a theme, I was a little lost.

To me it somehow felt very liberating and restricting at the same time. Liberating, because of the ecosystem; themes, plugins, hosting platforms, tons of helpful resources and support. Restricting, if and when you want to build a custom theme and don’t speak much PHP, general added complexity compared to a static site generator, having to deal with hosting providers, updates and added maintenance work.

But depending on the requirements, WordPress might actually make a lot of sense as a publishing platform (well, of course. It powers 40% of the web). My blog used to be hosted on Github Pages with Jekyll as the site generator until I made the switch to WordPress a couple of months ago. What I did struggle with was finding a setup that offered a smooth workflow around managing a custom theme with self hosted WordPress instance.

This article is an attempt at fixing that and aggregating some useful tips. I’ll try to cover the following:

  • A self hosted WordPress website that’s affordable yet stable
  • Continuous deployment pipeline for custom themes
  • Backups that are reliable
  • CDN and caching
  • Securing the website

Let’s get started.

Platform setup

I decided to go with AWS Lightsail one click WordPress install. You’ll find more information on the Bitnami WordPress page about the stack. It is lightweight and runs perfectly fine on a 512MB RAM / 1vCPU instance. Once behind a CDN and page cache, the website can handle a fair number of visitors.

Continuous Deployment (CD) pipeline (optional: Continuous Integration)

This step assumes you have a custom WordPress theme or source code of a theme available on a GitHub repository. You only need to follow this step if you think you’ll be making frequent changes to your theme files and would like to have a pipeline for the automatic deploy of the theme (say, for example, when you commit a change to the master branch of your repository). Alternatively, you can always create a zip file of the theme and upload it manually via the WordPress admin panel if you prefer to keep things simple.

Assuming you have a theme hosted on GitHub, you’ll need to make use of Travis CI to build your code (if there’s any CSS or JS that needs to be transpiled), test it (if there are any checks) and then upload the files to the AWS LightSail instance using secure copy (scp). Following are some resources to help you get started.

Backups

For backups, I’m using a couple of strategies but I think either one should suffice for my usecase.

AWS Lightsail snapshots

I’d recommend enabling automatic daily snapshots of your instance in AWS Lightsail. So if things go very south, you will lose 1 day’s worth of data at most. Since my blog’s content is rarely updated, this means this works near perfectly.

WPVivid WordPress plugin

WPVivid is a nice plugin that offers more precise backups, meaning you can choose to backup just your database, or files, or both. It also has cron functionality and offer 12 hourly backups (more frequent if you’re a paying customer). WPVivid allows you to transfer the backups to Google Drive, AWS S3, Dropbox among many other third party providers.

Server health monitoring and alerts

I’m using New Relic to monitor the health of the WordPress instance. It isn’t necessary as AWS Lighsail already comes with basic dashboards for monitoring CPU performance and burst usage (giving a rough idea about whether the server is sweating under load), but if you’d like to go a bit fancy with the whole monitoring thing and set up alerts for throughput, error rate etc, New Relic is quite good.

New Relic really shines at showing you the external services your instance is talking to, database operations and the CPU usage share per plugin that you have installed on your WordPress website. That information can help you debug any services / plugins that are slowing down your website or doing something strange behind your back.

AWS metrics
Metrics in AWS Lightsail

Metrics in New Relic
Metrics in New Relic

Both AWS Lightsail alerts and New Relic alerts support multiple channels, so feel free to use SMS, email, Slack or whatever your preferred way of getting alerted is.

CDN and Caching

My go-to CDN for any personal website is Cloudflare and that is what I’m using here. I didn’t have any problems with the admin interface behind the CDN and all seems to work very well. I have a page rule that overwrites cache control headers from WordPress and forces everything under /wp-content/* to be cached.

For page caching, I’m using a plugin called WP Total Cache. It was the most popular performance optimization plugin and was recommended to me. It has a “Page Cache” option which needs to be enabled and set to use disk as cache store.

Security

To secure the Lightsail instance, I’m following some basic good practices and a plugin to help me set up some blocking rules.

  1. Lightsail instance is as close to stock as possible making sure there are no random packages installed from my side on the instance.
  2. Disable port 80, and if you’re using a reverse proxy CDN like Cloudflare, only allow Cloudflare IPs to your origin server.
  3. As with Lightsail, WordPress installation should be close to stock with minimal plugins.
  4. Wordfence WordPress plugin for
    1. 2FA authentication
    2. Banning incorrect login attempts, or login attempts using generic usernames like admin, administrator or root.
    3. reCAPTCHA on the login page (you’ll need API keys from Google)
    4. Disable xmlrpc if you’re not planning on using apps. Enable 2FA on it, or disable login via xmlrpc.
    5. Go through all the options that Wordfence has to offer and use whatever makes sense for your use case. I found them to be quite useful and intuitive.
  5. In general, keep stuff up to date.

Conclusion

That’s it for this article. If you have any questions or suggestions, please feel free to write to me. Thank you for reading.