SiteKickr Web Development

Using Lazy Definition to load JavaScript libraries on demand

I've been told on more than one occasion not to spend too much time perfecting the performance on a website or app before gauging consumer interest. In other words, don't spend time hyper-optimizing something that hasn't yet proven it's worth. Only after a project has taken off does it warrant your valuable time for performance tuning.

That is one philosophy. The other way of thinking is the "now or never" approach. If you don't optimize all your code as you go along, you may very well never afford the time to do it again. If your app takes off, you'll be too busy handling feature requests to revisit that old sloppy code you wrote just to get the project out the door faster.

Regardless of the stance you take, some optimizations are so simple to implement and provide such a dramatic performance enhancement that they're hard to overlook, even in a time crunch.

One optimization that fits this description is lazy definition. If you're already familiar with the term, then you may be wondering how it can improve performance in any significant way. This brings us to another concept called lazy loading. They sound similar, right? But, they're actually two different techniques that can work together to improve the load time of a website.

 

Lazy Definition

Is Lazy the right word?

I'm not one to argue with the terminology set forth by our computer science pioneers, but… When I think about the term lazy, poor coding practices or inefficient algorithms come to mind.

I could just as easily call the old array bubble sorting method "Lazy Sorting". So, you could see how this terminology could easily confuse a programmer who is first hearing about this technique. The term "Lazy Loading" doesn't quite convey the fact that a function is redefining itself to execute in a more optimized way the next time it's called.

A better term might be "On-Demand Definition". It doesn't carry the same ring, but it's a little more accurate as to what's actually happening.

Because of JavaScript's liberal nature, you're actually able to let a function definite itself. It defines itself by replacing it's own code, once it executes for the first time. Let's demonstrate this with an example:

myFunction = function () {
    if (browser === 'IE') {
        myFunction = function() {
            return 'This is IE.';
        }
    }
    else if (browser === 'Chrome') {
        myFunction = function() {
            return 'This is Chrome';
        }
    }
}

So what's going on here when myFunction is executed?

  1. A conditional checks a variable which indicates which type of browser is being used.
  2. Depending on the result, myFunction is redefined, replacing the entire code within myFunction

Essentially, once myFunction is called (let's say browser = 'IE'), it is now defined as:

myFunction = function() {
    return 'This is IE.';
}

After a single call to the function, it self-optimizes by removing the unnecessary conditional.

Okay, cool, I guess. But, how do we use that to improve page load time in a significant way? That's where lazy loading comes in.
 
 

Lazy Loading

When to use Lazy Loading

Lazy loading sounds so good that you might be tempted to use it as a rule, rather than when it makes the most sense. Here are a few tips that might help:

Use Lazy Loading when
  • Only a small percentage of your visitors will require that the library be loaded
  • The loading condition is based on a user's action, such as clicking a link
  • The library to be loaded is large and will take time to load and execute (be sure to offer a spinner or other progress bar to your user)
Do not use Lazy Loading when
  • The majority of your users will require a library
  • Other portions of your code will require using the library, regardless of user action
  • The library to be loaded is small and executes quickly. In this case, you should minify and merge it into your main JavaScript file.

If you've read about lazy loading, you'll find that there are two definitions floating around. The first, which I consider to be inaccurate, refers to lazy loading as the act of loading a JavaScript library asynchronously and as late as possible. This implies that the library will always be loaded whether it's actually used or not.

The second definition, which is more accurate, refers to loading the library only when it's needed. Another term to describe this is on-demand.

This sounds great, doesn't it? Why wouldn't we do this for every library that we need to load? The reason is, loading a library requires an HTTP connection, which requires a lag time. If a user were to click a link, then have to wait for a library to load before something happened, that wouldn't be a good experience.

Consideration should be taken when using lazy loading. Use it when a library is used only by a small percentage of your users. For instance, let's say have a link in the footer of your website which causes a lightbox to load. If this link is seldom used, and is the only link that requires a lightbox, you might consider lazy loading the lightbox library.

 

Combining Lazy Loading with Lazy Definition

So we now know that lazy loading can enhance performance, and through lazy definition we can "improve" a function's implementation when it's called for the first time. It's only natural to combine these two techniques into a powerful method for loading a JavaScript library on-demand.

In the example below, I demonstrate this concept with Jack Moore's Colorbox jQuery plugin. In this case, I have a link on the page which is not only seldom used, but is the only link which needs to open in a lightbox. Naturally, I don't want to load the lightbox library with every page load if it will only be used 1% of the time.

Instead, I'll wrap the $.colorbox function in my own function, which on first call will load the library, then pass the parameters on to the $.colorbox function. Afterwards, the function redefines itself to simply call the $.colorbox function (essentially removing the AJAX call to load the library).

 

myColorbox = function(args) {
    $.ajax({
         url: '//cdn.jsdelivr.net/colorbox/1.4.4/jquery.colorbox-min.js',
         cache: true,
         dataType: 'script',
         complete: function() {
             $.colorbox(args);
             myColorbox = function(args) {
                 $.colorbox(args);
             }
         }
    });
}

 

Using this method, I never need to concern myself with whether or not the library is available, the function takes care of that for me by replacing itself using lazy definition. In any situation, I can simply call the function:

myColorbox( { href: 'http://www.sitekickr.com/', 
              iframe: true, 
              width: 500, 
              height: 500, 
              opacity: .5 } );

All the work of loading the library first and prevent an attempt to load the library again is done when the function redefines itself on the first call.