AssetHat 0.4: Load CSS and JS faster. Your assets are covered.

May 6, 2011 § 7 Comments

You don’t have to read too far through before finding this simple principle:

Every millisecond counts. Nothing is more valuable than people’s time.

For front-end developers, this means making CSS, JS, and images load at top speed. “But,” you exclaim, “why should I care, when my 96-core computer with an SSD and fiber optic internet already loads everything ridiculously quickly?!”

Think about the commuter who is loading your website over 3G (or worse, EDGE). Or the coffee shop hipster who is loading your website over slow, unhip public wifi. Or the desk employee who is loading your website with an ancient desktop tower that the company can’t/won’t upgrade. As caring, responsible front-end web devs, we have to help users make the best of their hardware and network connections, which are often beyond their control.

As Google has noted, . If your website is also selling something, you’ll surely want to move users through checkout swiftly.

At Mint, we’ve poured considerable effort into optimizing our clients’ Rails websites to load front-end assets—CSS, JS, and images—as quickly as possible. For a web production agency like this, the obvious move is to keep these optimization techniques private, and claim them as a competitive advantage. However, we wanted to help make the web a faster place, so last year, we released an early version of the AssetHat gem. This gem comprises some of our best front-end dev techniques to drop into your own Rails app.

It doesn’t end there. Today we’re releasing AssetHat 0.4, which adds Rails 3 support and integration with LABjs, the popular JavaScript loader. There’s also a where you can find more code and documentation.

Performance

How has AssetHat 0.4 been performing on our client sites? Take a look.

AssetHat reduced page load time for every website tested, sometimes by up to 46%:

Chart showing seconds until DOM is ready in each website

Figure 1: Seconds until the page's DOM is ready. Fast sites improved a bit; slow sites improved dramatically.

These websites benefited from better user experiences and faster customer conversions.

To get a sense of scale: Websites A and B handle about 6,000 views/day, which means a savings of up to 2.6 hours/day. Websites C, D, and E handle about 400,000 views/day, or a savings of up to 91.8 hours/day. That’s 91.8 collective hours of staring at a screen, waiting for the internet to respond.

Every site’s either held steady or increased by up to 31 points:

Chart showing Google PageSpeed scores for each website

Figure 2: Google PageSpeed scores; some sites improved dramatically. Website G is unfortunately so media-heavy that optimizing CSS and JS couldn't salvage it.

With numerical support from Google itself, we know these websites are on the right track to better Google search rankings.

How it works

AssetHat covers the usual web performance optimization bases:

  • Combine CSS and JS files to reduce the number of times the desktop/mobile browser has to contact the server. (Contacting a server is slow.)
  • Minify CSS and JS by removing unnecessary comments and whitespace.

It can also find image URLs in your CSS, then rewrite them to point to your CDN of choice, or add cache-busting ?abc123 strings to each URL based on when the image was updated.

That’s just the easy stuff. AssetHat really shines when you want to use the incredible work from the JS community, like jQuery, YUI, or LABjs.

For example, when you need to use jQuery, you typically have to download a copy for local development. Then, for best performance in production, switch to loading jQuery from Google’s CDN. Here’s the usual Rails way:

  <%= javascript_include_tag Rails.env.production? ?
        'http://ajax.googleapis.com/[...]/1.6.0/jquery.min.js' :
        'jquery-1.6.0.min.js' %>

Whenever you need to upgrade to the latest jQuery, you have to change this in all of your layouts. Bummer.

Here’s how you do it with AssetHat:

  <%= include_js :jquery %>

Add the jQuery version to a single config/assets.yml file, and that’s it. AssetHat loads your local copy of jQuery in development, and knows how to find it on Google’s crazy-fast CDN in production. If you didn’t bother to download jQuery, AssetHat uses Google’s CDN as a fallback.

Now, let’s say you have several JS files to load:

  <%= javascript_include_tag 'jquery-1.6.0.min.js',
                             'common.min.js',
                             'search.min.js',
                             'app.min.js' %>

However, because there are so many scripts, you realize that it’s worth trying a popular script loader like LABjs to see how much it improves performance. So you start over:

  <%= javascript_include_tag 'LAB-1.2.0.min.js' %>
  

What a hassle. With AssetHat, just set up a bundle in config/assets.yml:

  js:
    bundles:
      app:
        - common
        - search
        - app

Ready to go. Here’s how to load jQuery and your bundle normally:

  <%= include_js :jquery, :bundle => 'app' %>

And here’s how to switch on LABjs mode:

  <%= include_js :jquery, :bundle => 'app',
                          :loader => :lab_js %>

Add your preferred jQuery and LABjs versions to the config file if you haven’t already (example), and that’s it. If you don’t have a copy of LABjs locally, AssetHat knows how to instead load it from cdnjs, which uses high-speed Amazon Cloudfront servers.

This is just the most common LABjs use case. If you want to fine-tune it even further, you can have the best of both worlds:

  <%= include_js :lab_js %>
  

In this example, common is not a dependency for search, so allow either to execute as soon as possible—whichever happens to loads first—rather than always forcing common to execute first.

The future

We’re using AssetHat in all of our client sites in production; it’s under active development in many environments. Future versions will add support for Rails 3.1, support for more libraries on cdnjs, and shorter HTML (e.g.,

Follow