Tags: JavaScript

Javascript minification patterns: Structuring for maximum compression

{2 Comments}

When it comes to JavaScript compressing and minification, I’m sure that most of us out there take it for granted and really don’t think too much about how the minifier we are using actual works or what it can actually minify. It turns out the actual structure of our code can have a major impact on the amount of minificaiton can actually perform.

The golden rule of most minifiers is to start by compressing the name of any non public variables. The problem  is that most of us don’t realize exactly what is and what isn’t public when it comes to JavaScript. Fortunately, there are some common patterns and practices we can use to help minifiers do their job and get the most out of the process.

Structuring for maximum compression
Structuring for maximum compression

Lets have a look at the following very contrived samples:

Sample 1

var pubsub = {};

//Support
pubsub.supportMethod1 = function () { /*...*/; };
pubsub.supportMethod2 = function () { /*...*/; };
pubsub.supportMethod3 = function () { /*...*/; };

//Main
pubsub.publish = function (message, data) { /*...*/; };
pubsub.subscribe = function (message, func) { /*...*/; };
pubsub.unsubscribe = function (token) { /*...*/; };

the end result cannot be nearly as compressed as if we were to restructure our code into a more module design. The following shows how we might go able restructuring our code:

Sample 2

var pubsub = (function () {
    var //Support
        supportMethod1 = function () { /*...*/; },
        supportMethod2 = function () { /*...*/; },
        supportMethod3 = function () { /*...*/; },

        //Main
        publish = function (message, data) { /*...*/; },
        subscribe = function (message, func) { /*...*/; },
        unsubscribe = function (token) { /*...*/; };

    return {
        publish : publish,
        subscribe : subscribe,
        unsubscribe : unsubscribe
    };
}())

This altered code is very different to the first sample not only because it uses a module design patterns but this structure has the by product of protecting the variables.

This is a critical distinction as it means that minifiers can compress all variables except those that you are explicitly choosing to make public. This is possible with the first pattern but in my experience most developers writing JavaScript aren’t as conscious about this as they should be and in the end it results in code that is more bloated than it needs to be – even though its minified.

To show just what the difference can be look at the results when using Google’s Closure Compiler:

Sample 1

Original Size: 351 bytes (152 bytes gzipped)
Compiled Size: 166 bytes (91 bytes gzipped)
Saved 52.71% off the original size (40.13% off the gzipped size

var pubsub={supportMethod1:function(){},supportMethod2:function(){},supportMethod3:function(){},publish:function(){},subscribe:function(){},unsubscribe:function(){}};

Sample 2

Original Size: 405 bytes (180 bytes gzipped)
Compiled Size: 98 bytes (76 bytes gzipped)
Saved 75.80% off the original size (57.78% off the gzipped size)

pubsub=function(){return{publish:function(){},subscribe:function(){},unsubscribe:function(){}}}();

NOTE! The example I have provided is very trivial and one could argue that when these function have code, the saving in percentage terms wouldn’t be anywhere near as much. But in my experience since I started learning more about how JavaScript scoping works (what is public and hence what a minifier can’t compress) and making sure my scoping was correct, I started seeing:

  • More than decent reduction in file size as it turns out very few variables need to be public (in some cases none – meaning all variable names can be reduced)
  • I could understand my code better as I wasn’t choosing shorter names in an effort to help the minifier to its job
  • Lastly the quality of my code increased dramatically as it turns out the Module Pattern when implemented in JavaScript is fantastic way of of writing “good” JavaScript – which is one of the holy grails of web development

Best of luck!

UPDATE:

As @lordeagle pointed out, you can even take this further by assigning the values of statements that contain reserved words to variables. For instance, if you have a method that has multiple uses of “this”, at the start of the function you could assign this to a variable.