Organizing JavaScript for minification, maintenance and performance

While developing intranet framework at work, i decided to look into a more practical approach to JavaScript organization than the dreaded “script file per page” in its most common form. The obvious disadvantage of this method is that it’s often very difficult to optimize. Consolidating scripts into a single file is a pure nightmare because you start accidentally executing scripts on pages where they shouldn’t run. Let’s take a look at this example to see the basic issue at hand. Assume you have a couple of scripts that look like so:

$(function() { $('.some-selector').val('This is Page A!'); });
$(function() { $('.some-selector').val('This is Page B!'); });

Somewhere down the road you decide to optimize and consolidate scripts into a single file to save bandwidth. Well, you just opened a can of worms because you’ve got multiple selectors executing out of context on the same markup as soon as you combine your script files.

Wouldn’t it be nice to organize scripts into modules which spread across intuitive namespaces? Wouldn’t it be even better if your scripts formed a really clean API?

Well, as it turns out this isn’t very difficult to achieve. Let me introduce the Module Pattern which you should start appreciating right after reading the linked article. Okay, here is what it does and why it’s awesome.

The JavaScript Module Pattern

In very simple terms, the module pattern allows you to organize your scripts into modules (O rly?), which sit under conveniently accessible and intuitive “namespaces” for the lack of a better word (obviously JavaScript doesn’t actually support namespaces).

I will not go into any great detail here explaining how to use this pattern since the article linked above does it very well. What I would like to do is provide some quick samples and outline the benefits of this approach. Here is the basic structure of a Module Pattern.

window.webPortal = {}

webPortal.account = (function () {
    var bindOverlays = function () {
        // This is a private method
    };

    var bindAccountRegistrationEvents = function () {
        /// <summary>
        ///     You can even document you methods! Wow! By the way I'm private.
        /// </summary>
    };

    return {
        init: function () {
            // This is a public method
            bindOverlays();
            bindAccountRegistrationEvents();
        },
        doSomethingElse: function (param1, param2) {
            // Another public method
        }
    };
})();

I’m just scratching the surface with the sample above. First, this script creates a namespace object webPortal. Then it gets assigned an anonymous function, which is addressed as webPortal.account. Notice the () on the last line of the script. This is called the function closure and it executes the anonymous function immediately after it’s declared returning the object containing our public and private members.

As you can see we’re using encapsulation here to handle some private class logic. For instance, bindOverlays() could be a member that is responsible for registering a div overlay for certain events. This member is invoked by the public init() method, which, in turn, is invoked by the page. Really simple, yet powerful.

In the case of my Web Portal framework, my page classes only exposed the init() method. All of the event bindings and ajax requests were handled by private members. Any parameters during page initialization were passed to the init() method from the page using an associative array as shown below.

$(function () {
    webPortal.account.init({ accountId : '2343346656', useCache: false });
});

As you can see, the possibilities are endless here and the flexibility is amazing. You can bang out a really nice-looking API. In fact, I used the following pattern to create a set of shared objects which provide a way to access a common way to bind certain events, run ajax requests, log events and etc.

So what does this buy us? Here is a few things i could think of.

  • Easy optimization gained from encapsulating script logic into modules. We can easily serve page scripts in one combined chunk without worrying about conflicts.
  • Great run-time performance and very minification-friendly. Initialization suffers a bit here, but it’s almost negligible and is outweighed by the benefits.
  • Encapsulation provides a way to hide any JavaScript framework behind the scene. I personally think this is big**. There are so many JavaScript frameworks out there. It’s jQuery today and something else tomorrow. So, if you are using a framework try to keep public method signatures as generic as possible. (For instance, if you’re using jQuery, don’t pass jQuery selectors to public members.)
  • Clutter-free markup. Need I say more? Decoupling page markup and UI logic is always great in my book.
  • Easy maintenance. This is really a nice side-effect of all points above.

Hopefully, I’ve convinced some folks to try this out. Give it a shot. It really is a very powerful way to handle scripting complexity. Granted this may not be the best way to go about doing this, but if you want to look at a great real-world implementation of this pattern take a look at the script source on StackOverflow.