Redesigning SitePoint: Caching & Speed

Michael Sauter
This entry is part 4 of 4 in the series Redesigning SitePoint

Redesigning SitePoint

One of the objectives for developers of the new SitePoint website was to make it fast. Really fast.

Before we dive into what we did, I want to show you where we’re coming from:

  • Time to first byte: ~3 seconds
  • Document complete: 6-9 seconds
  • HTTP Requests: 100+ (first time), 35+ (repeat)

As you can see, this is pretty bad. As a developer, it just hurts to see those numbers. We want to create world-class code and 100+ requests for one page just isn’t.

But, is speed just something we developers care about or does it actually matter for your business?

A lot has been written on this topic, and the uniform conclusion is that loading time affects your bottom line. Another one is that page speed is one of the factors in Google’s search engine ranking.

If you’re still not convinced, a faster backend lets you serve more traffic with the same infrastructure, saving you money. Finally, an increase in load time as been proven to lead to an increase in pageviews per visit.

So, what exactly factors into a speed-up in load time? When we think about how fast a website is, we’re most likely talking about various aspects of speed. I think it’s good to ask two questions and answer them separately even if they correlate somewhat:

  • How many requests can we handle (how fast is the backend)?
  • How fast does the website feel (how fast is it perceived by the user)?

We’ll look at each of these questions, and then see how we answer them here at SitePoint.

How many requests can we handle?

This greatly depends on how long one request takes when it comes in, and how many of the incoming requests we have to actually process instead of serving cached versions. At SitePoint, we’re in the lucky position to serve relatively static content, which is the same for all our visitors. This allows us to cache most of the responses, meaning most requests never hit our app.

Instead, our proxy serves in front of the website serve the response. If you check your network traffic in the browser, you’ll see most pages are served with a 304 Not modified header.

Speeding up the time it takes to generate a response is trickier, as we can’t change the internals of WordPress. However, using plugins such as W3 Total Cache, we can cache some of the more expensive parts, for example making use of the WordPress Object Cache.

How fast does the website feel?

Besides the time needed for the response to come in, we also need to address the following:

  • How long does it take until the browser starts rendering?
  • How long does it take until the site is ready to be used?
  • How long does it take until the browser finished loading?

Technically speaking, we want to keep the time until the DOMContentLoaded event is fired at a minimum. Quite often, a website will feel much faster without having to change any backend code when you just reduce the time to DOMContentLoaded.

Before telling you how we do this here at SitePoint, I want to recap some general rules when it comes to frontend performance:

  • Make as few HTTP requests as possible (combine your assets)
  • Download as little as you have to (minify everything and serve it gzipped)
  • Cache everything as aggressively as possible
  • Include JavaScript at the bottom

To achieve this, we generated three files during our build process:

  • Stylesheet
  • JavaScript that needs to go into the head (which is barely anything)
  • JavaScript that can go just before the closing body tag

All of those files are minified. Now, to be able to cache them as long as possible without having to worry about invalidation, we include the md5 hash of the content into the filename, like so: styles-3ed1dd875e184c186ecdce24235a714d.css. With that in place, we cache each particular file for a very long time using the Expires header (Etag would work equally well).

If you’re using frameworks like Rails or Symfony2 to build your website, you get all of this for free. SitePoint however is running WordPress, which unfortunately does not have any support for this out of the box. There are a couple of plugins, but in the end, we decided to not use any of them.

Instead, we process our assets during build using Grunt. The reason for this is that it’s impossible to have reliable asset processing from within WordPress on a multi-server setup without a shared storage, which we don’t use anymore.

Results

With all that in place, we’ve got quite a responsive website, serving a huge amount of traffic quite easily. Let’s see what this looks like in numbers:

  • Time to first byte: ~1 second
  • Document complete: 1-2 seconds
  • HTTP Requests: ~20 (first time), ~7 (repeat)

For the homepage, a typical page load will fire the DOMContentLoaded event under two seconds, with it being around one second for cached responses. Of course, these times will vary depending on your location and whether the internal cache of the page you access has been primed.

Overall, coming from 6-9 seconds and 100 requests, this is an amazing achievement which we hope you enjoy every time you point your browser to www.sitepoint.com.

Redesigning SitePoint

<< WordPress Multi-Environment: Setting Up SitePoint

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • johnie

    it looks awesome!

  • Oliver Clevont

    One thing which slows down SitePoint for me is your use of Google Fonts. When Safari on iPad is downloading the fonts (and it can’t cache it for long since my cache is quickly filled up by other stuff), it displays a page with a background but no text. This lasts for a while depending on my connection speed. You should use Google’s Font Loader which substitutes a local font while the foreign font is downloading.

  • mVeliki

    Nope, I can count 50 HTTP requests.

  • Sam

    I’d be very interested in knowing more about your Grunt and WordPress workflow and deployment process.