How To Make Your Website Load Ridiculously Fast
The Importance of Speed
Most of us know that website speed is important. You've most likely heard about the effect page loading time can have on page abandonment. Google, Amazon, Mozilla and Yahoo have all shown why website speed matters, with Amazon for instance increasing its revenue by 1% for every 100ms of improved page load time. In 2010, Google announced that site speed would be used as a search ranking factor. But we already know that website speed is important because we all have experienced slow websites and the frustration of feeling like we're back on 56k modems. Even though our own website wasn't in the slow website bracket, we wanted to show our users (and our clients) how making some small tweaks can actually make your website lightening fast. Here's how we did it.
How We Made It Ridiculously Fast
We identified some key areas for improvement and took time to think about who our key visitors are and what their requirements were. Here's a summary of what we did - more detailed information is at the end of this post.
- Removed CakePHP and MySQL as they were overkill for our website's need. They were only really being used to serve blog posts and make development slightly easier.
- Hosted the site inside an Amazon S3 bucket in the new Sydney, Australia environment.
- Compressed all PNG images using ImageOptim.
- Hosted all images on a CDN (Content Delivery Network) which replicates world wide for super fast delivery. We currently use Edgecast hosted by GoGrid but Amazon also has it's Cloudfront CDN. See a comparison between Edgecast and Cloudfront.
- Used multiple subdomains (ie, cdn1.inlight.com.au and cdn2.inlight.com.au) to distribute all image requests across to over come the multiple request limits web browsers impose.
The observational speed when visiting the new website (that's the one you're reading from now) vs the previous website shows an obvious improvement in overall speed. In terms of actual performance:
- Latency reduced from 220ms to 30ms for every request. For every 10 non concurrent requests (images, CSS, JS) you are saving approximately 2 seconds of page load time.
- On average the website is 10 - 15x faster. You can replay the test if you are interested or view the video below.
Faster Than Bing!
We are even faster than Microsoft's search engine landing page.
We still have some more ideas on how to further increase the website speed and we'll look to improve on these iteratively over time.
- Reduce the number of images loaded on each page by merging small images into sprite maps.
- Lazy load images, videos, slides, code snippets. The concept of "Lazy Loading" is based on the idea that you only download items as the user scrolls / arrives at that location of the page. Sebastiano Armeli presented a great talk at MelbJS and Web Directions South this year called Lazy Load Everything.
- GZIP all content. The gzip compression mechanism is supported by almost all browsers these days
The processes included some simple steps and some more complicated. At the very least it's worth looking at your own website architecture and whether you are delivering the best experience to your visitors. Simple steps such as relocating your hosting nearer to your audience and using content delivery networks to distribute your requests, will go a long way in improving the website experience. We definitely had fun turbo charging the website. If you'd like to chat with us about your website or find out more, feel free to contact us.
Technical Details For You or Your Developer
Below some more detailed information about the individual steps for you to read over or share with your development team. We have also included a template project structure that you can start using straight away to replicate the compiled HTML approach hosted for hosting on Amazon S3.
Web browsers limit the number of concurrent connections from a single domain to between 2 - 6 connections. An easy and fast way to speed up your website is to create multiple subdomains to host your static content (ie, images, CSS, JS) on. These are CNAME records that should all point to the CDN hosting your static content. This effectively increases the number of concurrent web requests your browser makes. We added cdn1.inlight.com.au and cdn2.inlight.com.au (both pointing to the same location) and divided them amongst our images to increase the page load speed. Be careful not to add to many subdomains as each variation requires a DNS lookup.
One of the main reasons we used PHP in the past over plain HTML is to allow us to create templates and snippets of reusable code that we can use across all pages (ie, rather than having the footer code repeated in every page which would make it very difficult to change, we just include a single file and have only that one location to update if a change is required). Again this is great for development and we wanted to maintain that development efficiency but not at the expense of page speed. So we contructed a website template that uses Jade to give us that PHP like "includes" and allow us to use functions, etc. We then use the Grunt script to bundle these all up into the final compiled HTML version.
Here you can download the template project. It requires you to have NodeJS & NPM installed. When you have extracted it use terminal to `cd` into the base directory (the one with the grunt.js file in it) and run `npm install`. This will download all the npm packages required. Then run `grunt` which will compile all the "src" directory files into the "bin" directory. Play around in the src directory and look through the grunt.js file to see how things are put together. During development I `cd` into the "bin" directory and run `serve` via command like (run `npm install serve -g` the first time) - this serves the files at http://localhost:3000. That is a lot to take in, but have a look around and read up on npm and Grunt - also feel free to contact us if you run into trouble.
Hosting on Amazon S3
There are a few things to note here. One it's just static file delivery, so you can't load up dynamic content on the fly server side or submit a form to your server (because there is no server). For instance if you wanted to add comments to the blog posts you might look at using a client side solutions such as DISQUS.
The other thing to note is that if you want to have nice looking URLs without .html on the end you are going to have to partake in some trickery. Basically the solution we came to was to compile the pages out into index.html files that are placed in the folders that we want the URL to be. So for instance the contact page isn't contact.html it's /contact/index.html and because web browsers natively look for index.html when visiting a folder reference it all works out pretty nicely.
One last item that we weren't able to resolve on Amazon was to serve the website via their Cloudfront CDN because Cloudfront uses CNAME records to resolve to the correct resource. CNAMEs unfortunately don't work nicely when you have inlight.com.au without a subdomain in front (so it works fine with www.inlight.com.au). There are options such as naked url redirection however it's not a clean approach. Our current solution is to host the website in two s3 buckets (inlight.com.au and www.inlight.com.au). Then using A records we can point them directly to the Sydney S3 IP address and it all resolves fine. The performance downside, however is that international visitors are being served content out of Sydney - for us our Australian audience is our key visitor group.
Again if you would like to know more or discuss further how to speed up your website, please contact us.