It’s a strong title for a post, I know, but having discovered that two friends didn’t know this at last night’s LRUG, I wanted to share it.

Let’s put this in bold for impact.

When you add <%= javascript_include_tag :defaults %> to the top of your Rails layout, you’re adding 146kb to your page load.

And, being Javascript, that all loads serially. This is slowing page load down a lot.

Now, I’m sure if you’re building a whizz-bang AJAX app you need all that. But I reckon a lot of Rails projects don’t use anywhere near all that. So throw some out!

The Scriptaculous libraries are quite big: dragdrop.js is 30kb, controls.js is 29kb, effects.js is 34kb. If you don’t need that lot, get rid of it. prototype.js alone is 56kb. The case for the Prototype library is easier to make… but if all you’re doing is some simple DOM scripting – show/hide, for instance, do you really need 56kb of library functions to do it? Or can you do it in < 10kb with some home-made functions? If so, strongly consider doing that. And if you’re not using any Javascript in your application… why have you get any of it in there? It can all go – that’ll speed page load up no end!

I’m not saying there’s no place for this stuff – there is. Should it be included in Rails Core? Absolutely. I just don’t think that it should be called the “default” option; <%= javascript_include_tag :all %> would make a lot more sense. And by sticking it into the basic scaffolding layout, it becomes a part of many people’s first experience with Rails – and they assume it’s default behaviour. And so I also think it should be left out of scaffolding – perhaps replaced with <%= javascript_include_tag "prototype", "application" %> at the least.

User experience, usability, and accessibility aren’t just about the content or code of the page; they’re about how the user experiences the page. If it takes an age to load, it makes the app less usable. If you’ve got huge page size, you’re excluding anyone on a slow connection. So next time you’re skeletoning out a Rails app, take a moment to think if you really need any Javascript. If you don’t, <%= javascript_include_tag :defaults %> can go straight in the bin. Then, when you come to progressively enhance your app at the end with Javascript (which is, let’s face it, how you should be doing it), you can include only the files you need – and keep your users happy at the same time.

5 comments on this entry.

  • Michael Houghton | 15 Sep 2006

    I use a conditional loading trick that helps me keep down the load times for users not visiting parts of my site that need particular features.

    Basically, these two helper functions allow templates and helpers to identify their layout requirements:

    # a way of identifying features the layout needs to load
    def require_page_support(*scr)
    @page_scripts ||= {}
    scr.each { |s| @page_scripts[s] = true }
    end

    # used in the layout to query the need for features
    def load_page_support?(*scr)
    @page_scripts ||= {}
    scr.inject(false) {|matches, s| matches || @page_scripts[s] }
    end

    Then I can do things like this, in a helper or view:

    require_page_support :image_search

    And in the layout, that can be serviced by:

    ….

    This way I force myself to think about the code required for site functions, rather than just blanketing myself in javascript (and other things) that I might not need.

  • Michael Houghton | 15 Sep 2006

    ugh, html tags swallowed:

    <% if load_page_support? :image_search -%>
    <%= javascript_include_tag “image_search” %>
    ….
    <% end -%>

  • Nerdmaster | 16 Aug 2007

    If you use these JS pages in one central place, it really won’t hurt you to use them everywhere. A one-time hit of 150k is bad if you don’t need it anywhere in your app, but let’s not forget that browser caching means it is indeed just a one-time hit (check your logs, but in my case anything in public/ is cached nicely).

    Be careful how much garbage you include, but don’t try to optimize every single page hit when the browser is specifically built to be efficient at “retrieving” the same static content multiple times.

  • Marco | 24 Oct 2007

    Yes, is very harmful, I had tag default to my application.rhtml, now I had removed this tag and my application is very more speed .

  • Steven G. Harms | 3 Jan 2008

    Why not define a “lite” layout and then the full :defaults “heavy” layout?


    class myController < ApplicationController
    layout :lite_on_js
    def new
    ...
    end
    ...
    end

    If doing the JS-lite is more common, change the default layout for that controller to use a layout that includes no JS, then you could manually trigger a JS heavy layout when you needed the kitchen sink with :defaults by using:


    render :layout=>:js_heavy

    It’s just another way to go, but needlessly including kbs of un-used JS is certainly Not Right ™.

    sgh