I spent a lot of time optimizing page loading speed on GirlsGuideTo. The result is pages that load almost instantly initially and on subsequent loads; and while I’m proud of the work I’ve done in getting these pages zippy, there was no real secret sauce involved. Here I’ll discuss techniques anyone can use to make their web pages load with amazing rapidity, all without breaking Google Analytics and other scripts you might already have installed.
Speed It Up
The first ingredient in our speed cake is head.js. While head.js has a number of components – media queries and dynamic CSS among them – the reason it initially became popular, and the reason I’m talking about it now, is its basic, core functionality. Head.js allows you to asynchronously load your page’s scripts. This might not sound like an enormous time savings, but consider this: do you use Google Web Fonts or Adobe’s TypeKit? Chances are you do, since everyone loves fonts. But fonts must be downloaded by the client browser, a process that usually occurs in the page’s head (before dom rendering has even begun), slowing down the rest of the page load while it waits.
And your user sees an empty browser while they’re waiting. That’s unacceptable.
Here’s what the code looks like for GirlsGuideTo:
Of course I didn’t hand-code that myself, I used the super helpful headjs-rails Gem to put this in my application.html.erb’s head:
Pretty easy, huh? Give it a shot and you’ll see your page load times start really blazing.
Turbolinks is ridiculously easy to install. Simply add it to your Gemfile and then, in your application.js, add this line:
Now Fix It
If you followed my advice up until this point, you might be stunned to discover your Google Analytics and
$(document).ready() stuff has completely broken. No worries! We’ll fix it, and it’ll be quick and easy to do so.
This is the easiest thing to correct.
$(document).ready() now fires before all your scripts have finished loading, since each script is loaded asynchronously and separately. So you’ll either see weird behavior from it, or it won’t execute at all (since $ will be undefined, as jQuery has yet to load). Simply replace all instances of
head() is called by head.js when your scripts have loaded. Something like this would make sense:
1 2 3 4 5 6 7 8 9
Google Analytics will load correctly on your initial page load, now. But unfortunately it won’t load on any subsequent pages, since additional pages are called via Ajax. We need to hook into one of Turbolink’s events to correctly record users visiting our site:
1 2 3 4 5
page:change is called every time Turbolinks fetches and renders a page: when it does so, we call Google analytics manually to inform it to track the current page view.
This should get you 95% of the way to having pages that are incredibly fast and work very well. One last caveat is that any script that loads on
$(document).ready() must now also load on
page:change as well: ready is not called when the page is already loaded, after all. So if you have CoffeeScript like this:
You’ll want to add this as well:
1 2 3 4 5
Remember this is only for scripts that you’re sure are loaded after jQuery – scripts loaded asynchronously need to use
head() instead of