Loading YUI: Seeds, Core, and Combo-handling

By YUI TeamOctober 17th, 2008

Kweight of common YUI baseline assets.

With the 2.6.0 release of YUI, the YUI Loader now supports combo-handling for both JavaScript and CSS files coming off of Yahoo’s CDN. YUI Loader is the utility that understands the YUI module structure and dependency list and can load any YUI component on the page on-demand. The addition of combo-handling makes YUI Loader an even more viable option for many implementations, because you’re never more than two HTTP requests (one for JS, one for CSS) away from downloading the requirements for any YUI component(s) to your page (not including image assets).

In this short article, I’ll take you through three common approaches to loading YUI on the page and review the filesize breakdown and benefits of each approach. All filesizes discussed here are minified and gzipped KB.

1. Using YUI Loader as a Seed File

YUI Loader is a 9.4KB file. It packages the Yahoo Global Object, the Get Utility, and the YUI Loader engine, including all the dependency metadata required to load additional YUI components on demand. With just YUI Loader on the page, you can load, say, the TabView Control as follows:

// Instantiate and configure Loader:
var loader = new YAHOO.util.YUILoader({

    // Identify the components you want to load.  
    // Loader will automatically identify
    // any additional dependencies required for 
    // the specified components.  We could specify
    // as many components here as we wish:
    require: ["tabview"],

    // The function to call when all script/css resources
    // have been loaded
    onSuccess: function() {
        //This is your callback function; you can use
        //this space to call all of your instantiation
        //logic for the components you just loaded.
        //In this example, we'd instantiate a TabView 
        //Control here:
        var myTabs = new YAHOO.widget.TabView();
    },

    // Combine YUI files into a single request (per file type)
    // by using the Yahoo! CDN's combo-handler.
    combine: true
});

// Load the files using the insert() method.
loader.insert();

(Live demo.)

Loader is the smallest available YUI seed file; from this 9.4KB base, you can bootstrap anything else in the library with a single HTTP request for JavaScript. Let’s look at the K-weight profile for this request in which we use YUI Loader as a seed file to bootstrap your JavaScript dependencies for the TabView Control.

Loading TabView with YUI Loader

So, our initial baseline K-weight was 9.4KB; YUI Loader then downloaded the rest of YUI Core (Dom and Event) along with Element and TabView, all a single 13.3KB download.

2. Using YUI Loader Plus Core as a Seed File

A second common approach to loading YUI is to use the YUI Core (Yahoo, Dom and Event) plus YUI Loader to serve as your seed file. Here’s what that might look like on the page:

<!-- Combo-handled YUI CSS files: --> 
<link rel="stylesheet" 
type="text/css" 
href="http://yui.yahooapis.com/combo?2.6.0/build/tabview/assets/skins/sam/tabview.css">
<!-- Combo-handled YUI JS files: --> 
<script type="text/javascript" 
src="http://yui.yahooapis.com/combo?2.6.0/build/yuiloader-dom-event/yuiloader-dom-event.js"></script> 
<script>

(function() {
	//create Loader instance:
    var loader = new YAHOO.util.YUILoader({
        require: ["tabview"],
        onSuccess: function() {
        	//when TabView is loaded, instantiate Tabs:
        	var tabView = new YAHOO.widget.TabView('demo');
        },
        combine: true
    });
    
    //When our target element is ready, bring
    //in the non-blocking, combo-handled script
    //download.  We can use Event here because
    //we've loaded YUI Core at the top of the page:
    YAHOO.util.Event.onContentReady("demo", function() {
    	loader.insert();
    });

})();
</script>

(Live demo.)

This seed file is bigger than YUI Loader alone — 17.4KB versus 9.4KB. But it confers some big advantages:

  • You have access to Event Utility’s event listener methods and its crucial page-timing methods (like onDOMReady and onContentReady) right away;
  • You have access to the Dom Collection’s swiss-army knife of DOM convenience methods right away.

Because most pages in a YUI-driven application are going to use both Event and Dom, this is often a good universal foundation from which to bootstrap YUI-dependent modules.

In the scenario where we’re loading TabView, here’s how the JavaScript flow breaks down with YUI Loader + YUI Core as our foundation:

Loading TabView with YUI Loader + YUI Core as a foundation.

The overall K-weight is about the same as with the simple YUI Loader seed; we have a heavier initial load, but immediate access to the goodness of YUI’s Core. And our subsequent HTTP request to complete TabView’s JS requirements drops to a small 5.4KB.

3. Combining All Requests in a Single File

Where loading scripts on-demand doesn’t make sense for your application (for example, if some of the core interactions on the page have script-driven enhancements that you want to render as quickly as possible), you can still take advantage of combo-handling on the Yahoo CDN by configuring your request on the Dependency Configurator. (Here’s a configuration for TabView using combo-handling.)

Here’s what that might look like on the page:

<!-- Combo-handled YUI JS files: -->
<script type="text/javascript" 
src="http://yui.yahooapis.com/combo?2.6.0/build/yahoo-dom-event/yahoo-dom-event.js&2.6.0/build/element/element-beta-min.js&2.6.0/build/tabview/tabview-min.js"></script>
<script>
YAHOO.util.Event.onContentReady("demo", function() {
	var myTabs = new YAHOO.widget.TabView("demo");
});
</script>

(Live demo.)

Best practice according to Yahoo’s Exceptional Performance guidelines would be to put this single file as close to the bottom of the page as possible, allowing the content and design to be processed before the browser hits your JS files. (Note: this is one reason why you might find approaches 1 and 2 useful — putting the 17.4KB YUI Loader + YUI Core file at the top of your file has minimal performance impact, and it allows you to load other JavaScript-dependent modules onDOMReady where appropriate.)

Summary

The takeaway here is that there are several ways to leverage combo-handling, and YUI Loader’s support for combo-handling, to bring the power of YUI into your application with minimal HTTP requests.

Here are some common implementations of YUI components using the combo-handler; this visualization is, again, of minified and gzipped K-weight for the JS dependencies:

K-weight for common YUI components.

Any of these single HTTP requests weighs less on the wire than the image above. As I’ve discussed elsewhere, the a la carte design of YUI means that you can add components to any of these payloads at a big discount because you’ll be adding only incremental dependencies. For example, the DataTable payload in the image above could have TabView added to it with just a 3.5KB additional cost. Using YUI Loader and its new combo-handling functionality makes this process even more performant and responsive in your applications.

7 Comments

  1. I was confused by a couple of things. In example one the comment on the page itself says “This example loads the YUI Loader, then brings in Dom, Event, Element and TabView” but all I see is Tabview being loaded. Below the code (but I could not figure out from the snippet where it went so I jumped to the exampled and viewed source) we learn (paraphrasing) “This example loads Tabview and the loader takes care of loading Dom, Event, and Element.” That may sound like a small difference, but to this noob was confused.

    Next, when we get to method two I think we learn that one would never want to use method one. Perhaps method one should be described as “just so you see the big picture”. As it is, I find myself wondering when or why I would use #1, ie, what advantages it offers (since it is hard to imagine using YUI without DOM and Event).

    The description of method 3 completely lost me. The motivation is “when on-demand won’t work” so my first thought is that I do not know what on-demand means, because on-demand means “use it and it will be there”. Then the example given for when it won’t work is just vague “script-driven” “core interactions” we want to render “as quickly as possible”…I find myself as a noob wondering what all that means, and an actual example of a page that won’t work and why would eliminate a lot of confusion.

    Finally the method three commentary says “this file should appear as late as possible” and ends up explaining that that is why we should use method one or two. Hunh? Method three is why we should use method one or two? Then why am I being told about method three? Guessing: use method three if one’s page does not require the core during construction of the page, which won’t be often if one is having any fun at all with YUI.

    Overall I sense there is a lot of good stuff in this article, but I find myself working hard to figure out what that good stuff is.

  2. @Kenny — Wow — I really failed you with this one. Sorry about that.

    Here are a couple of followups: 1. You’re absolutely right — Loader brings in all the required files that it perceives are needed for a given implementation. So when we ask for TabView, it looks at what’s on the page and gives us anything else we need to use TabView. 2. Why would you use method 1 instead of method 2? Well, if you really wanted the lightest seed file, 1 is the best option. In the case where you’re not going to be using any scripts in the initial paint of the page and everything is going to be layered on unobtrusively, this is the lightest starting point. But (3.), it’s often the case that you *do* need to do thing like attach event listeners in the course of building a page, so and method 2 is good for that, and it’s a good, performant compromise. 4. As for the final method, you’re right — I didn’t convey that very well. The goal is to have a page that works well without JavaScript, and putting the whole JavaScript payload at the top of the page generally needs to be done only when the page *requires* JavaScript to function correctly. If you take this single-file approach, though, putting the file at the bottom of the page *is* a good idea — that means that the page painted and functioned without the script, and the JavaScript was just there to add enhanced functionality.

    Sorry for the confusion — please let me know if you have further questions.

    -Eric

  3. Hi Eric,

    Great overview, thanks; I just have a question about best practices (and scoping) when loading multiple components.

    Let’s say I have something like require: [X, Y,Z], where X, Y and Z are arbitrary YUI components.

    Let’s also say that I have non-trivial instantiation logic for each of these components.

    My question is how best would/could I structure my onSuccess() method to keep the all the instantiation logic from clashing?

    I’d like to generate the loader config script on the server, perhaps with $module=>$setUp pairs, and my thought is that I need to use function literals themselves wrapped in parentheses to get what I’m after. (My trouble is that it’s precisely here that, for me at least, JavaScript gets confusing… ;-))

    Thanks again,
    Carlton

  4. @Carlton,

    I think the best approach, if I understand your problem correctly, would be to define each of your instantiation/configuration blocks as a separate “module” in YUI Loader.

    http://developer.yahoo.com/yui/examples/yuiloader/yl-addmodule.html

    Call the insert() method on the modules in the order you want them to fire (ie, in the order you want your components to instantiate). Let YUI Loader do the heavy lifting for you — it will calculate dependency trees for you and load whatever is missing (and do it with combo-handled requests) as needed, and only when needed.

    This may mean a few additional requests, but the modularity it gives you is worth it in many cases.

    If I’ve missed the boat on your question here, let’s take the conversation over to YDN-JavaScript.

    Regards,
    Eric

  5. [...] quick way to add Term Extractor to your application this may be of interest. The YUI dependencies (comprising the YUI Core + YUI Loader) are 17.4KB; the TermExtractor script is 1KB. Leave a comment | Trackback « Imagination [...]

  6. [...] 除了代码的可读性稍稍有一点点降低外,使用Combo Handler服务大大的降低了HTTP请求数,同时也减少了URL代码量,这对于Web性能优化来讲至关重要。所以,随后YUI从2.6.0开始,其核心组件YUI Loader内置了Combo Handling功能,即使用YUI Loader时,通过配置combine属性就可以把要加载的多个JavaScript或CSS文件按照使用Combo Handler服务的形式合并起来,这时只要静态文件的服务器支持Combo Handler就行了。在YUI中当combine配置为true时,CDN默认是使用Yahoo! CDN(http://yui.yahooapis.com),所以没有任何问题。这正是YUI最迷人的地方之一。 [...]

  7. [...] 除了代码的可读性稍稍有一点点降低外,使用Combo Handler服务大大的降低了HTTP请求数,同时也减少了URL代码量,这对于Web性能优化来讲至关重要。所以,随后YUI从2.6.0开始,其核心组件YUI Loader内置了Combo Handling功能,即使用YUI Loader时,通过配置combine属性就可以把要加载的多个JavaScript或CSS文件按照使用Combo Handler服务的形式合并起来,这时只要静态文件的服务器支持Combo Handler就行了。在YUI中当combine配置为true时,CDN默认是使用Yahoo! CDN(http://yui.yahooapis.com),所以没有任何问题。这正是YUI最迷人的地方之一。 [...]