Effort focus for page load time optimisation

Should I optimise my site? The short answer is an obvious yes. The more detailed answer is that it is not always worth the time to do it and you need to identify areas that make the most sense.

TLDR readers:

  • Latency and ping times are important for global reach. 50 requests could be a problem with a high ping or latency time.
  • Making sprite sheets is not worth it if you have only 5 non-critical sprite graphics
  • concatenating JS and CSS into single files with zip compression is worthwhile. Lazy loading assets/CSS/JS can be really complicated.
  • The Grunt task runner (NodeJS tool) is good great FANTASTIC! Check out my grunt config post for more details.

I recently updated an e-commerce website for a client (earlybirds.com.au). Earlybirds is a long standing client of mine since 2009. I inherited it as a flash based website with no SEO. I then upgraded it to use the GAIA flash framework and added SEO support. Later we made the full switch to an AJAX based site with simple content transitions to try and keep the rich and unique feel of Earlybirds. It has been a long journey with solid improvements. The latest achievement has been optimisation and page loading. It has not been easy to optimise given the flash legacy style of rich content and graphics. Images simply can’t be compressed more than they are and account for more than 60% of the initial page load size. Below are the steps I took and considered in optimising the website for a faster load.

1. Reduce requests

The more requests you have, the greater that ping times and latency issues will affect the end user. This is particularly true for users far from the server or on (typically slow and weak) mobile connections. Modern browsers also only download a maximum of 6 files concurrently. Also consider that each request/asset obviously has to be handled and probably rendered which then increases rendering time for the browser or device.

Reducing the requests affects a large audience but it is not always so important. German users accessing a website hosted in Germany would hardly be affected given their high tech infrastructure and small connection distances to the servers. In this case the mobile audience is more important to consider. For Earlybirds, we have seen a large uptake of mobile access which we presume comes from new mothers in hospitals. We also have New Zealand users accessing the server in Canberra (Australia) which warrants some concern.

In short:

  • consider mobile usage and connection speeds of your audience
  • consider global reach and distance to your web server

2. Merge and compress resources

Optimising images for the web is one thing but it only goes so far. For Earlybirds we use SASS for CSS management compiled by Compass triggered by our Grunt task runner. We also use Grunt to lint, concatenate and minify our JS. Further, we output gzipped versions for those clients that can receive them. Our output is then something like: earlybirds.min.js, earlybirds.min.js.gz, earlybirds.css and earlybirds.css.gz. We use Apache to detect the compression headers sent by the browser and send either the .gz (compressed) version or the uncompressed but minified version if the header is not sent.

In short:

  • output single CSS and JS files that are minified (as small as can be)
  • output compressed versions of the minified files for browsers accepting compression (nearly all these days)
  • HTML should be zipped or use DEFLATE on the fly (mod_deflate for Apache users)

2.1 A bit on image sprites

It’s a growing trend to try and avoid using icon graphics these days. Font solutions are much more flexible and can be easier to manage than image sprites. Font Awesome is one such font that includes vector based “font icons”. CSS has also improved dramatically allowing for easier drop shadow effects and has reduced the need for specialised graphics. SVG could also become the next big thing once <=IE8 is no longer of interest. Earlybirds has about 5 sprite graphics (within our control) which could be merged into one sprite sheet but this would be a small win. For those interested, Compass allows for easy compilation of multiple sprites into a single sprite sheet with supporting CSS to make life easier.

In short:

  • avoid sprites unless absolutely necessary and use font icon solutions (consider making your own font if need be)
  • if using sprites then use Compass to generate an easy to use sprite sheet

3. Use a CDN

We use jQuery hosted on a google CDN. If for whatever reason google goes down (think end of the world) then we default to our local copy. This is also handy for local development offline (when travelling without always having internet access).

4. Ensure styles and scripts are loaded in the correct order

CSS can only be loaded in the header except in very unique lazy loading scenarios. Javascript should be loaded before the closing body tag except where certain scenarios are relevant. If for instance a CDN is used to fetch jQuery (which may already be cached by the end user anyway) and your whole app or website relies on jQuery before the user can see anything then loading it in the head tag probably makes sense. Visual components and popups that are never loaded instantly like modal popup displays can be loaded after the user can begins interacting with the site via a technique called lazy loading. This style of lazy loading can however be too time consuming to manage and get right. Lazy loading JS, CSS or even HTML needs to be considered for more speed critical scenarios or when large complex apps are in use.

In short:

  • CSS in the head tag
  • jQuery and similar core components in the head tag (often needed before anything else will work given strong dependencies)
  • Remaining JS before the closing body tag (should be 1 single JS file)
  • lazy load ONLY if you really need to and know what you are doing. TIP: RequireJS

5. Queue Image slideshows

We were loading all 7 images in a slide show at once. This is not necessary. We removed the use of the src attribute from the embedded image tags in favour of data-src which should also be SEO friendly. We then preloaded each slider image on demand or rather 1 image earlier than required so that the fade transition effect still looked seamless. This is also true for any other kind of teaser element and affects the mobile experience the most.

Note that the (soon to come) ‘picture’ element and similar shims may one day be viable to support multiple image resolutions but it will be a long time before they support bandwidth requirements.

What did I leave out?

I haven’t gone into detail about mobile usage. There are many tricks one can use to speed up page load time. Below are a few starting points:

  • use the client side application cache (can be tricky)
  • consider “offline first” practices for caching assets
  • use multiple domains or CDNs where possible (increase number of simultaneous resource downloads)
  • become a caching pro and PROPERLY understand cache busting
  • turn tiny graphics into binary and include in CSS/HTML to reduce requests
  • load on demand (think twitter or Facebook feeds as you scroll down the page)
  • High DPI graphics (high resolution or retina ready) have no good solution. Wait for the picture tag or use a shim to get support sooner. Consider not sending mobile devices HDPI graphics even if they support them.

Further resources

WebPageTest.org is an incredible tool to analyse ever part of the page loading process. There are even algorithms that they have invented (open source) to create the most useful speed analysis stats around (the speed index). They even allow testing in different browsers from different test sites around the world = Totally wicked stuff!

Leave a Reply

Your email address will not be published. Required fields are marked *