Rails asset tag expansions

If you're using edge rails you may have noticed that you can now define your own JavaScript expansions (if you're not on edge this will be included in the imminent 2.1 release). The default expansion that comes with rails looks like this:

javascript_include_tag :defaults
javascript_include_tag :defaults

Which grabs application.js as well as the prototype/scriptaculous javascripts and includes them all (only do that if you need it all - it adds ~150kb to your page). But say you've got a line which looks like this:

javascript_include_tag 'my_js_file', 'another_js_file', 'and_another'
javascript_include_tag 'my_js_file', 'another_js_file', 'and_another'

And say you want to include the same set of files on a different page - it turns out Rails makes it really easy to DRY this up. Make a new file in the config/initializers directory (I call my asset_tag_expansions.rb) and add a line like the following (don't forget to restart your server afterwards):

ActionView::Helpers::AssetTagHelper.register_javascript_expansion :my_js=> ['my_js_file', 'another_js_file', 'and_another']
ActionView::Helpers::AssetTagHelper.register_javascript_expansion :my_js=> ['my_js_file', 'another_js_file', 'and_another']

Now in your views you can simply put:

javascript_include_tag :my_js
javascript_include_tag :my_js

You can of course register as many of these as you like, and include as many of your own expansions on the same javascript_include_tag line as you want, e.g.:

javascript_include_tag :my_js, :another_expansion, :and_another
javascript_include_tag :my_js, :another_expansion, :and_another

The same applies to stylesheets:

ActionView::Helpers::AssetTagHelper.register_stylesheet_expansion :public_styles=> ['reset', 'layout', 'home']
stylesheet_link_tag :public_styles
ActionView::Helpers::AssetTagHelper.register_stylesheet_expansion :public_styles=> ['reset', 'layout', 'home']
stylesheet_link_tag :public_styles

Finally, although you're getting all that onto one line, each asset file is still being requested separately by your browser, each time making another nasty expensive HTTP request. Rectify that:

stylesheet_link_tag :public_styles, :cache => 'public'
javascript_include_tag :my_js, :another_expansion, :and_another, :cache => 'public'
stylesheet_link_tag :public_styles, :cache => 'public'
javascript_include_tag :my_js, :another_expansion, :and_another, :cache => 'public'

This bundles up your three stylesheets and concatenates them into a single file, which is called public.css in this case. In the example above this means two less trips to the server to retrieve the stylesheet files, therefore a faster loading page. This is helpful because it enables you to maintain small, targeted stylesheets in development which makes finding the relevant CSS declarations easier, without the performance hit of all those HTTP requests when in production.

One final option is to use the :all expansion, which just grabs everything in the stylesheets or javascripts directory. Be careful with that though as you've got to be sure assets are being loaded in the right order (especially for JavaScript), and that you really need all that asset weight on each page.

Share Post:

What to Read Next