Lazy Loading: Optimal User Experience

Now that I’ve covered Non-Blocking Pages, it’s time to dig deeper into the world of Lazy Loading and how it applies to the Optimal User Experience.

To kick things off, I’m going to start with what every Software Developer loves to do and paste the definition from Wikipedia:

Lazy loading is a design pattern commonly used in computer programming to defer initialization of an object until the point at which it is needed. It can contribute to efficiency in the program’s operation if properly and appropriately used. The opposite of lazy loading is Eager Loading.

Spot on. First, let’s take a look at Eager Loading to better understand the problem.

Eager Loading

<head>
  <script src=”scripts/master.js”></script>
  <script src=”scripts/plugin1.js”></script>
  <script src=”scripts/plugin2.js”></script>
  <script src=”scripts/plugin3.js”></script>
  …
  <script src=”scripts/plugin12.js”></script>
</head>

Does this look familiar? Unfortunately most of us have seen this… too many times. The first solution that might come to mind is to consolidate these scripts into a single file, which is both a great performance consideration, and also outside of the scope of this topic, so let’s assume for now that there are reasons for keeping these resources separate. The question I want to ask here is, are all of these needed right now?

Let’s take a look at another example, wherein the requirements of my application are a bit less straight forward:

<head>
  <script src=”scripts/master.js”></script>
</head>
<body>
  <div id=”widget1”></div>
  <script src=”handlers/widgets/widget1”></script>
  <div id=”widget2”></div>
  <script src=”handlers/widgets/widget2”></script>
  <div id=”widget3”></div>
  <script src=”handlers/widgets/widget3”></script>
  <a href=”#” onclick=”runWidget3(); return false;”>Run Widget3</a>
  <div id=”widget4”></div>
  <script src=”handlers/widgets/widget4”></script>
  <a href=”#” onclick=”runWidget4(); return false;”>Run Widget4</a>
  <script>
    function runWidget3 () {
        $(“#widget3”).widget3(); // run widget3
    }
    function runWidget4 () {
        $(“#widget4”).widget4(); // run widget4
    }
  </script>
</body>

This is a pretty typical example to find in Go Daddy products like WebSite Tonight and our other site builders where content is more modular and code may be generated on the fly. What’s important to get out of this example is that the first two widgets are run automatically and immediately, while widgets 3 and 4 are not needed until the user performs an action (clicking a link, in this case). But, if I don’t need the last two widgets until the user performs an action, why am I loading them? Because I’m over eager, of course!

Time to Get Lazy

Now let’s take that last example and adopt an asynchronous loading pattern demonstrated in my Non-Blocking Pages article.

<head>
  <script src=”scripts/curl.js”></script><!-- my AMD loader -->
  <script>require(“js!scripts/master.js”);</script>
</head>
<body>
  <div id=”widget1”></div>
  <script>require(“js! handlers/widgets/widget1”);</script>
  <div id=”widget2”></div>
  <script>require(“js! handlers/widgets/widget2”);</script>
  <div id=”widget3”></div>
  <a href=”#” onclick=”runWidget3(); return false;”>Run Widget3</a>
  <div id=”widget4”></div>
  <a href=”#” onclick=”runWidget4(); return false;”>Run Widget4</a>
  <script>
    function runWidget3 () {
      require(“js! handlers/widgets/widget3”, function() { // load widget 3 on-demand
        $(“#widget3”).widget3(); // run widget3
      });
    }
    function runWidget4 () {
      require(“js! handlers/widgets/widget4”, function() { // load widget 4 on-demand
        $(“#widget4”).widget4(); // run widget4
      });
    }
  </script>
</body>

Aside from the fact that my page is now asynchronous and thus Non-Blocking, I’ve determined that because widgets 3 and 4 are not needed until the user performs an action, I won’t even load them until the user performs the action. Also worth noting is that subsequent clicks will not re-load the widget, but will still perform the callback function.

Ok, so that’s not bad, but perhaps not a common enough example to apply. This practice can be applied to other similar situations, such as loading a Modal plug-in only when the user clicks an action that requires the usage of a Modal (another real-world case leveraged in some of our products); even the content of the Modal can be loaded on-demand.

My Content is Lazier Than Yours!


Lazy Loading of content can be applied to virtually any Content Type, and by no means is specific to Scripts. Above is a screenshot of an Image Collection plug-in that we include in WebSite Tonight and other Go Daddy site builder products, and is the perfect use-case for aggressive Lazy Loading. We’ve demonstrated hundreds, and even thousands, of images in a single collection, and it loads so quickly that it’s almost as if wizardry were at play! We leverage two critical techniques to accomplish this:

  1. Only load the images in view (including thumbnails) – In the screenshot above, only about 3 medium-sized and 7 thumbnail images need to be loaded, regardless of whether there are 7 or 700 images in the collection. While outside of the scope of Lazy Loading, it’s worth noting that we further optimize this by only loading the necessary image size to fill the area, as there is no sense in downloading an 8MP image for a 300×300 box.
  2. Disable loading when the Image Collection is out of view – Many websites have multiple Image Collections on a given page, or simply have Image Collections towards the bottom of their pages. So, why load images for a plug-in that is not even in the view of the user? Our plug-in listens to resize and scroll events to better predict when the user actually needs to see the images, allowing the rest of the page to load that much faster.

It’s a Lazy World After All

My objective was not to list out every use case for how and when to leverage Lazy Loading, but rather to demonstrate a couple strong use cases to get you thinking about the concept and how it might be of use in your applications. I’ve found that adopting this pattern has not only been very handy to achieve an Optimal User Experience, but it has also been a fun challenge that forces me to be creative with how I might adopt the pattern in other areas of my applications. It’s as much of an art form as it is a science.

I’d love to hear your stories about how you’ve adopted this, and similar patterns, to more intelligently load resources in your applications!

Aaron is responsible for driving innovation across Site Builder products, in addition to driving our shared UI framework. Aaron brings a wealth of technological passion to development architecture here at Go Daddy with over 14 years of product development experience. Connect with Aaron on Google+

4 Comments on "Lazy Loading: Optimal User Experience"

  1. Thanks, Aaron. I sincerely appreciate your educational info since my web site (on GoDaddy) is graphic intensive and uses a number of plug-ins for both content and advertising purposes . I’ll get started on the implementation of your advice as soon as I can… most likely in stages (for the older content) and more immediately for the future content.

  2. I love your articles. It helps me with a lot of dilemmas that I’m running into as a moonlighting web developer/designer.

  3. Great to hear! More on the way.

  4. Have you seen increased user engagement when lazy-loading has been implemented?

Got something to say? Go for it!

 
Traffic Log Image