A Strategy for Loading Page Specific JavaScript

Jeremy Morony ·

Since the introduction of the asset pipeline, managing javascript assets in a typical rails application is pretty straight forward. You figure out some structure for organizing the files under app/assets/javascripts/, concatenate them together with some directives in application.js, and that file is most likely included in a layout and you’re on your way. But what about those pesky page specific initializer scripts?

A popular approach is to use a strategy like this. The gist of this approach is to organize your page initializers in an object literal by controller name and action, something like

    index: ->
    show: ->

The document body is decorated with the current controller name and action. A document ready script extracts the controller and action, looks it up in the initializers object and executes the associated initializer. Generally the initalizer scripts are placed somewhere under app/assets/javascripts and included in the application.js bundle. This approach is perfectly fine, but a few minor things bug me:

  • Every initializer is included in the application bundle, bloating its file size
  • The page queries the registered initializers to see if it has work to do. I’d rather the initializer script told the page it has work to do when the document is ready.

An approach that has worked for me looks something like this:

I like this approach for a few reasons:

  • Only one initializer is included on a page.
  • It provides a convention for where page initializers will be located on the server.
  • Page initializers are set aside from the general purpose JavaScript.
  • The size of the compiled application.js file is reduced because the page initializers aren’t included in the bundle.
  • The initializer tells the page it has work to do.

The downsides:

  • There is an extra request to the server for the page initializer file.

You probably noticed the code at the bottom of the application.js file. This code doesn’t specifically have anything to do with the loading strategy outlined above, but it does complement it. It creates a namespace for your JavaScript, named after your rails app. Within this namespace it creates a page object. This object provides a few things:

  • A convenient place for storing data that you might need to generate while rendering the current action. Better to place that data here than on window where another object with the same name might be overwritten
  • A convenience method for registering document ready handlers. When the document ready event fires, the intializer is executed with the page initializer as the first argument. This structure should make it easy to unit test your initialization scripts.

This is obviously just one of many approaches out there. What other approaches have worked for you?