LABjs & RequireJS: Loading JavaScript Resources the Fun Way

Kyle Simpson, James Burke | August 18, 2010

 

JavaScript resource loading has many different concerns that bear on how it is approached. An increasing number of sites and applications are relying on complex systems of JavaScript resources and many developers are hoping for easier, faster and more maintainable patterns for dependency management. The authors of two open source projects, LABjs and RequireJS, discuss some different perspectives that accomplish those goals.

It may not seem so interesting to talk about JavaScript resource loading. We’ve had the <script> tag for about 20 years, so what else is there to talk about? In this article, we’re going to examine some use cases which need solutions that are more powerful and flexible than the basic <script> tag.

There is no single solution that meets all goals and needs. Not only are there various syntax options, but sometimes there are tradeoffs that depend on which use-cases are of primary concern. LABjs and RequireJS embody many of these tradeoffs.

What you should get from this article is a more thorough understanding of script loading issues, hopefully equipping you to make the decisions which make the most sense for your environment and needs.

This article will focus mostly on loading resources into browser-based environments, but as you will see later, the emerging server-side JavaScript phenomenon and the need to “load” server-side modules does have some influence on how browser loading may be approached.

Script Loading

Let’s first make sure we’re all on the same “page”. What we’re talking about is how to handle the need to load JavaScript files (either same-domain “locally” or cross-domain “remotely”) into a web page. As you’re certainly aware, this is usually accomplished with plain ol’ <script> tags.

But there are some significant limitations with <script> tag usage, especially as complexity or volume increases. First of all, usage of <script> tags in your HTML markup implies that you know at author-time all of the resources that must be loaded, and that you know any possible dependencies between them so that you can order your <script> tags correctly. For instance, if you have dozens of files that all have interconnected dependencies on each other, you have to sort through all that mess manually and figure out the proper <script> tag sequence, a task that can understandably be tedious and tax the development and maintainability standards of your site/team.

Secondly, until the latest generation of browsers, the <script> tag had some really unfavorable performance characteristics to it. Namely, <script> tags “block”, meaning they call a halt to everything else that’s loading/happening on the page, while they load and while they execute. Not only do they halt all other parts of the page, they even used to halt the loading of any other <script> tags.

So, if you had 10 <script> tags in a row, they would load in order, one at a time (aka, serially), executing after each load. Understandably this will lead to much slower page loads, especially if one of the resources is from a remote location that is either down or overloaded and responding slowly.

Even in the bleeding edge versions of the latest generation browsers, we’ve only seen partial improvement in this serial loading and execution. Most newer browsers are now smart enough to download your scripts in parallel, but they will still wait to execute them one-by-one serially. In addition, because the browser has to assume you may have something like a document.write() in the file, the browser must block page rendering while it executes each file. See Figures 1 and 2 for “waterfall chart” illustrations of how script loading and blocking behavior affects the rest of the page in different browsers.


Figure 1: script loading “waterfall” behavior in FF 3.0, serial load, serial execution

 


Figure 2: script loading “waterfall” behavior in FF 3.5+, parallel load, serial execution

Luckily, the browser allows us to do things asynchronously and on-demand, so we can address many of these performance issues by attempting to load our JavaScript files dynamically. There are dozens of different “JavaScript loaders” out there, of varying degrees of complexity and capability. Many of them are part of specific toolkits, such as the loaders included in Dojo and YUI.

This article will focus on LABjs and RequireJS as two solid solutions which are both completely toolkit-independent and both capable of solving some very complex resource loading issues.

While LABjs and RequireJS have different tradeoffs, there is a common set of benefits they both provide over basic <script> tags in HTML:

1. Dynamically created script elements thatavoid blocking browser rendering

By adding scripts to the page via dynamically created script elements, the browser will no longer block rendering waiting for the script to load, as shown in Listing 1.

function addScript(url) {
    var script = document.createElement('script');
    script.type = 'text/javascript';
    document.getElementsByTagName('head')[0].appendChild(script);
}

Listing 1: Simplified example of a function that dynamically creates a script tag and adds it to the DOM.

Injecting script elements on-the-fly has a dual-sided effect: the page will be “unblocked” so that it can continue loading its resources in parallel with the scripts, but this will also completely separate script loading from both the DOM-ready (DOMContentLoaded) and window.onload events.

If you are accustomed to attaching behavior to the DOM-ready/onload events assuming that this will ensure all scripts are loaded (as it does with normal <script> tags), this will no longer be true. Instead, you will need to use the loader’s callback mechanisms to ensure your scripts are loaded before executing additional code.

In addition, since the script can execute after page load, the script should not use document.write(), otherwise it will wipe out the content of your page. Scripts that use document.write() should not be loaded with a dynamic script loader.

While there are some tradeoffs with dynamically created script elements, the performance gains and flexible load options are well worth it.

2. Scripts can be loaded at any time

Since script elements are added dynamically to the page, scripts can be “lazy loaded” at any point of the pages lifecycle, for instance after a time delay or when a user clicks on a button. This can help amortize the cost of downloading your code over the lifetime of your page.

3. Specify script dependencies

Script loaders allow you to specify the dependencies among the scripts. The syntax and approach of handling dependencies is one of the major differences between script loaders, but they all give you more robust dependency control compared to regular <script> tags.

Why not just concat?

Before we dive into the specific loaders, it is important to address one specific question that often comes up when script loaders are being discussed: “Why do I need a script loader if I can just concat all my files together and load one file? Won’t that perform well?”

This is a complicated issue, but let’s just address it briefly. If you’re interested in a more thorough discussion, Kyle addressed “why not just concat?” as a full blog post.

  1. A single 50k file may take less overhead than two 25k files, but it will also tend to load in approximately twice as much time, because the browser can’t take advantage of parallel downloading. You shouldn’t load fifty 1k files either – that’d be crazy! But maybe 2 or 3 files in parallel might be quicker than one big file. Just try it and see.
  2. A single 50k file is cached completely together. Say this file is really composed of 5 different 10k files on your server, 4 of which are quite stable but one of which you change regularly (tweaking the UX of the site, for instance). Then every time you make even a one character change to the unstable file, all your users will now have to download a completely new copy of the single concat’d 50k file, even though well over 40k of that file didn’t change and probably won’t change. Maybe files should be packaged together based on their volatility/frequency-of-change to minimize wasted reloading?
  3. Some files may not be on your domain. It’s common that people load scripts from remote Content Delivery Networks (CDNs), like the JavaScript libraries. It’d be a performance anti-pattern to self-host such files just to concat them and serve them on your more limited bandwidth compared to Google’s pipes.

Point being: the right answer is not always one file. Downloading fewer files is generally better than downloading more files. For many sites, downloading anywhere from 1 to 3 scripts will be optimal. Every site/application will be slightly different, so you’ll just have to experiment and see. But odds are, you’ll end up with more than one script if you look at this issue closely.

Even if you do only have one script, you can still benefit from a script loader, so that the load of this one big mammoth file can be done in parallel with all other resources on your page. Even just doing that will significantly speed up the performance on your site. Try it, you’ll see!

Also, help me conduct some research with this baseline test that compares parallel loading to partial and full concatenation. It’s best if you click the three buttons in order, and repeat the process a few times. Results are automatically logged.

LABjs

LABjs (Loading And Blocking JavaScript) was conceived from the get-go as a convenience script loader. By “convenience”, I mean the primary goal was the simplest usage possible while fulfilling the underlying functional objectives. It was my hope that doing so would make LABjs accessible to the “long tail” of websites – that is, would be something that even the minimally capable web site owners would be able to implement LABjs script loading with very little knowledge of JavaScript.

As the development of LABjs progressed in its early stages, the near-universal remark made by those who examined and played around with it was that significantly improved web performance (ie, it reduced page-load times by speeding up JavaScript resource loading). It didn’t take long for me to realize this was and should be LABjs’ main functional target: achieve the most optimal performance optimization possible in script loading, and do so in a normalized way across all browsers.

So, LABjs is the performance script loader by design and by function. It’s crucial to understand this bias as we go forward.

Above, we discussed how <script> tag elements in the HTML markup of a page will block other page-resource loadings and thus hamper performance. But we hinted that dynamic script loading is effective at addressing this bottleneck. What this amounts to under the covers is dynamically inserting a script element into the DOM. When a browser sees this happen, it will still load and execute that resource, but it will not halt the rest of the page while it does so. The great part is that you can specify many scripts to load at once, and to the extent possible, the browser will download them in parallel, significantly reducing the overall load time.

The problem this introduces is that in many browsers, if you try to dynamically load two or more scripts at once, the browser will not ensure their order of execution. This means that if you have dependencies between two scripts, you immediately have a race condition where the scripts may not execute in the correct/intended order.

So, my goal with LABjs was to create a replacement for the <script> tag that would look as close to the <script> tag as possible, yet solve these performance issues by doing dynamic loading for the specified script. But it was also important to be able to specify when execution order for dependencies was important, so that LABjs could “wait” on execution order, but still be able to load all scripts in parallel for performance optimization.

This was a very difficult set of requirements to balance in a simple API, but the LABjs API is the result of my best attempt at that. See Listing 2 for a common example of some script tags, and the equivalent loading done with LABjs’ syntax in Listing 3.

<html>
<head>
<script src="script1.js"></script>
<script src="script2-a.js"></script>
<script src="script2-b.js"></script>
<script type="text/javascript">
    initScript1();
    initScript2();
</script>
<script src="script3.js"></script>
<script type="text/javascript">
    initScript3();
</script>
</head>
<body>
...
</body>
</html>

Listing 2: normal <script> tags

<html>
<head>
<script src="LAB.js"></script>
<script type="text/javascript">
$LAB
.script("script1.js").wait()
.script("script2-a.js")
.script("script2-b.js")
.wait(function(){
    initScript1();
    initScript2();
})
.script("script3.js")
.wait(function(){
    initScript3();
});
</script>
</head>
<body>
...
</body>
</html>

Listing 3: LABjs syntax for loading the scripts

As you can see, the LABjs syntax attempts to be as close to the markup it’s replacing as possible, so that it’s as easy as possible for web developers to convert existing markup to performance-optimized script loading. See Figure 2 for a comparison of normal <script> tag loading compared to performance improvements from using LABjs. Note that not only did the page-load go down from 16.84 seconds to 6.24 seconds (2.7x!) but also the page’s DOM-ready (the point when the page is useable to users) went from about 10 seconds down to about 0.4 seconds! That’s some major performance improvements, both real and perceived.


Figure 3: LABjs performance improvements

LABjs API notes

  1. $LAB always starts a LABjs chain, which is defined as all calls to .script() and .wait() chained off each other and the initial $LAB reference. You can create as many separate $LAB chains as you’d like, but they operate completely separately in pretty much every way. If you want to specify dependencies between two scripts that you want LABjs to respect in execution order, the two scripts must be specified in the same $LAB chain. On the flip side, if you have completely unrelated scripts and you want to segregate them to prevent any cross-influences, separate $LAB chains is the way to go.
  2. .script(…) can take any number of string parameters (representing the relative or absolute URL’s of script resources). The URL’s can be to any location, on the page’s domain or on another domain. For instance, you can use LABjs to load jQuery from the Google CDN and Google Analytics from the GA servers, along with several other scripts from your server.
  3. .script(…) can also take an array as any parameter (processed exactly how you’d expect), or it can take an object with key/value pairs. The object parameter syntax allows you control individual aspects of that specific script-loading, including the “type” parameter, whether to dupe-check the script source against previous loadings, etc.
  4. .wait() with no parameters is used to signal the $LAB chain that it should ensure execution order is preserved at that point in the chain. In other words, all scripts before a .wait() must execute (in whatever order) before any scripts after the .wait() can be executed. Again, .wait() will not in any way affect the loading in parallel, but only the execution order of the chain.
  5. .wait(…) with a function (or function reference) passed to it is the same as an empty .wait(), except that the function passed in will also be treated as a normal inline <script> tag’s code (see Listing 3). This is called “coupling” where you couple an inline script snippet to execute in the proper order of the rest of the chain’s execution.

The default behavior of LABjs is to load all scripts in parallel (including the “preloading” tricks if .wait()’s are present in the chain), and execute them each as fast as possible, unless a .wait() instructs otherwise. However, there are a number of configuration options which you can control the various behaviors with. These options can be set either globally (affecting all $LAB chains on the page), or per $LAB chain (affecting only that chain). See Listing 4 for an example of setting global and per-chain settings.

<html>
<head>
<script src="LAB.js"></script>
<script type="text/javascript">
$LAB.setGlobalDefaults({BasePath:"/some/path/"});

$LAB.setOptions({AlwaysPreserveOrder:true})
.script("script1.js")
.script("script2-a.js")
.script("script2-b.js")
.wait(function(){
    initScript1();
    initScript2();
});

$LAB
.script("script3.js")
.script("script4.js")
.wait(function(){
    initScript3();
    initScript4();
});
</script>
</head>
<body>
...
</body>
</html>

Listing 4: Setting $LAB defaults, globally and per-chain

See the API Documentation for a list of configuration options and what they do.

Advanced LABjs

It is often asked of me, “what if I need to conditionally decide at run-time what scripts get loaded?” That question, and several others of a similar vein, lead me to document here (in a very basic form) a technique which can be used to squeeze more advanced usage out of a chaining API like LABjs.

First of all, $LAB.script(…) can take an array, so you can programmatically build up the array in a variable, and then pass it to a single .script() call. However, this is limited in that you can’t exactly inject .wait() calls in the chain with this approach. Fortunately, for those needing that capability, there is a way!

The key is to realize that when you chain a function off a previous function’s return value, this is just a syntactic expressiveness, not a requirement. The intermediate return value, which in chaining is never seen but only indirectly used, can actually be stored in a temporary variable, and then used just like it was a call off the end of the chain.

What this means is, you can programmatically build up an array of elements that conceptually represent individual calls to a $LAB chain, and then simulate the chain calls by making a function call and storing the return value and using that return value as the object to make the next function call. See Listing 5 for an example.

<html>
<head>
<script src="LAB.js"></script>
<script type="text/javascript">
var _queue = ["script1.js",null], $L = $LAB;
</script>

...
</head>
<body>
<script type="text/javascript">
if (something) { // script 2 going to be loaded
    _queue.push("script2-a.js","script2-b.js",function(){
        initScript1();
        initScript2();
    });
}
else {  // script 2 not going to be loaded, so just init script-1
    _queue.push(function(){
        initScript1();
    });
}

</script>

...

<script type="text/javascript">
if (somethingElse) {
    _queue.push("script-3.js",function(){
        initScript3();
    });
}
</script>

...

<script type="text/javascript">

for (var i=0, len=_queue.length; i<len; i++) {
    if (typeof _queue[i] == "string") { // script string source found
        $L = $L.script(_queue[i]);
    }
    else if (!_queue[i]) { // null/false found
        $L = $L.wait();
    }
    else if (typeof _queue[i] == "function") { // inline function found
        $L = $L.wait(_queue[i]);
    }
}

</script>

</body>
</html>

Listing 5: Simulating a $LAB chain with a for-loop

LABjs going forward

Currently, and primarily, LABjs is a client-side performance-optimized script loader. It relies on the author to have knowledge of the dependency connections tree of their scripts so the proper $LAB chain can be constructed. This type of usage fits really well with most normal sites that already use <script> tags, but it’s a less natural fit for complex development environments with dozens of inter-connected modules with nested dependencies and such.

While that is certainly not the primary use case of LABjs, that doesn’t mean there’s no way LABjs can be useful in that environment. The goal all along, and now the primary development activity around this project, is to develop a server-side component for LABjs that can assist in these more complex tasks. The server-side LABjs component is itself being written in JavaScript, with the hope/goal of it being able to run in practically all server-side JavaScript environments, such as Node.js, Narwhal, etc.

The plan for the server-side LABjs is to be able to post-process (either at run time or at build time) HTML files and script files to determine the dependency tree/graph automatically, and generate the optimal LABjs chain(s) for those resources. It will take into account all the balancing logic mentioned above, including concat’ing files together (but not always down to one file). For instance, server-LABjs will be able to detect which files change more often and not, and make packaging decisions based on that data.

The goal of server-LABjs will be to complement client-side loading by providing a mechanism to optimize the usage of LABjs for the exact environment, automatically. In fact, when/where possible, usage of the client-loader will actually be avoided. You will always be able to trust that server-LABjs is doing its best to optimize script resource loading in your site/application.

But the other implication here is that you will be able to manage complex hierarchies of scripts/modules, even those with nested dependencies “annotated” directly in the script files, and not have to worry about keeping track of how LABjs can and should load these files. Server-LABjs will do that stuff for you! Now that’s optimized!

$LAB.summary()

Bottom line: if you want to load any script, from any location, at any point in the page’s lifetime, and do so in the most performance optimized way, while still maintaining execution order dependencies when necessary, LABjs arguably one of the strongest solutions available. Optimized loading is exactly what LABjs is designed to be the best at. Remember, it’s the performance script loader.

RequireJS

RequireJS has its roots in Dojo and CommonJS, so it encourages you to treat scripts as modules. How does a script differ from a module? Normally a script is just a JavaScript file that may add things to the global namespace and it can have implied dependencies. Modules try to limit their impact on the global namespace and be more explicit about mentioning their immediate dependencies.

I was hoping to create a script loader that would allow the better containment of modules that worked directly with CommonJS modules. However, the CommonJS group chose a format for their modules that assumed synchronous loading of modules from local disk. While it is possible to do synchronous loading of scripts in the browser via XMLHttpRequest, it does not perform as well as code loaded via script elements, it is harder to debug, and harder to do cross-domain requests for scripts, for example loading scripts from a CDN. In addition, I have some issues with the CommonJS module format.

RequireJS is focused on providing a browser <script> tag-friendly format for loading modules that tries to match the goals of CommonJS, but works well in the browser. While RequireJS gives you excellent tools to make modular Javascript, it also supports loading today’s browser scripts. RequireJS also comes with an optimization tool that allows you to combine and group your scripts into a smaller set of minified scripts that load quickly.

Listing 6 shows the basic format for loading scripts with RequireJS.

<html>
<head>
<script src="require.js"></script>
<script type="text/javascript">
//The scripts will be fetched in parallel
//and asynchronously, and they could be
//executed in a different order than specified below.
require([
        "script1.js",
        "script2-a.js",
        "script2-b.js",
        "script3.js"
    ],
    function(){
        //This function is called once all the scripts
        //have loaded and executed.
        initScript1();
        initScript2();
        initScript3();
    }
);
</script>
</head>
<body>
...
</body>
</html>

Listing 6: RequireJS syntax for the first LABjs example

Whereas LABjs supports enforcing execution order by inserting .wait()’s into the chain, RequireJS does not natively support executing asynchronously loaded scripts in a particular order. However, thanks to the efforts of Alex Sexton, as of RequireJS 0.12, the order plugin offers basic support for this feature.

RequireJS has a plugin architecture that allows you to add new types of loading or dependency types. There are plugins for i18n string bundles, fetching text files (which can be inlined by the optimization tool), treating a JSONP service as a dependency, and forcing execution order of the dependencies.

The order plugin uses the same underlying technique as in LABjs: the type=”script/cache” fake MIME-type trick to load scripts in parallel but be able to manually execute them when appropriate.

It should be noted this trick is only necessary/effective in IE, Chrome, and Safari. For Firefox/Gecko and Opera, the trick doesn’t work, but thankfully isn’t needed because those browsers will automatically ensure the proper execution order even with dynamically loaded script elements.

Plugins are denoted from the resource name by an exclamation mark, as shown in Listing 7.

<html>
<head>
<script src="require.js"></script>
<script type="text/javascript">
//Since the order plugin was used, the
//scripts will be fetched in parallel
//and asynchronously, but executed
//in the order specified below.
require([
        "order!script1.js",
        "order!script2-a.js",
        "order!script2-b.js",
        "order!script3.js"
    ],
    function(){
        //This function is called once all the scripts
        //have loaded and executed.
        initScript1();
        initScript2();
        initScript3();
    }
);
</script>
</head>
<body>
...
</body>
</html>

Listing 7: Using the order plugin to maintain script execution order

RequireJS modules

RequireJS encourages the use of modules. Modules in RequireJS are defined using the require.def() function call, where the name of the module, its dependencies and a function callback are given. The function callback is called once the dependencies are ready, and it is used to define the module. If the dependency also uses require.def() to define itself, then you can get a direct handle on the dependency in the function callback.

require.def("lamp", ["Light"], function (Light) {
    //This function is called once the "Light" dependency
    //module is loaded and defined. The function
    //argument, Light, will be a reference to the Light module.
    //You can also use require("Light") inside this
    //function to get the Light module.

    //The value returned from this function
    //will be the definition of the "lamp" module.
    return {
        light: new Light(),
        on: function () {
            this.light.on();
        },
        off: function () {
            this.light.off();
        }
    }
});

Listing 8: Defining a module with require.def()

Notice the name of the module and its dependencies do not include a “.js” suffix. You could use .js URLs directly to load scripts that do not participate in defining a well-scoped module. However, with items that define modules via require.def(), you should always use the same name for the dependency as the dependency uses in its require.def() call’s first argument. RequireJS will translate the name “lamp” to “a/path/to/lamp.js” to load the script.

RequireJS modules can avoid exporting values to the global namespace, and since all dependencies are referenced via string values, it makes it possible to have multiple versions of a module in a page.

The format of RequireJS modules is similar to CommonJS modules, and RequireJS has a command line script you can use to convert CommonJS modules to the RequireJS syntax, allowing you to reuse CommonJS modules in your browser-based development. If you have a server process that can bundle CommonJS modules in the CommonJS Transport D format, like Kris Zyp’s Transporter, RequireJS allows you to use that code directly via the RequireJS Transport D adapter.

Using modules, our main example could have its scripts written like so:

//Contents of script1.js:
require.def("script1", function () {
    //Do the initScript1() work in here
    //var script1 = ...;
    return script1;
});

//Contents of script2-a.js:
require.def("script2-a", ["script1"], function (script1) {
    //Do initScript2() work that only concerns script2-a here. Use
    //script1 as needed.
    return {};
});

//Contents of script2-b.js:
require.def("script2-b", ["script1", "script2-a"],
    function (script1, script2a) {
        //Do initScript2() work that only concerns script2-b here. Use
        //script1 and script2a as needed.
        return {};
    }
);

//Contents of script3.js:
require.def("script3", ["script1", "script2-a", "script2-b"],
    function (script1, script2a, script2b) {
        //Do initScript3() here. Use script1, script2a and
        //script2b as needed.
        return {};
    }
);

Listing 9: Script examples as RequireJS modules

RequireJS Optimization Tool

The RequireJS optimization tool makes it easy to combine scripts together, and you can configure RequireJS to priority-load those combined script layers up front, therefore giving you the best performance while allowing your JavaScript source to stay small and modular.

Best of all, since the optimization tool is a command-line tool, you do not need special server side gear for it to work, and its output is deployable to static file systems and CDNs.

If the optimization tool was used to combine the require.def() versions of script2-a.js and script2-b.js into a layer called script2layer.js, then Listing 10 shows how you could code the HTML to get the fastest performing code using three script requests.

<html>
<head>
<script src="require.js"></script>
<script type="text/javascript">
//You can pass a configuration object as the first
//argument to require. "priority" tells the loader
//to download that set of scripts first, in parallel
//and asynchronously before tracing other dependencies.
require({
        priority: ["script1", "script2layer", "script3"]
    },
    ["script1", "script2-a", "script2-b", "script3"],
    function(){
        //Do any page-level work you wanted
        //with all of those modules here
    })
;
</script>
</head>
<body>
...
</body>
</html>

Listing 10: Script examples as RequireJS modules

By using the Optimization tool with the priority configuration option, you can then play with the right number of scripts to download to give you the best performance. Since require() can be called at any time during the page lifecycle, you can delay loading some scripts until a later user action.

Comparing LABjs and RequireJS

LABjs works best in pages with today’s scripts that need to be efficiently loaded in a particular order, and the dependencies can all be tracked at the top level. LABjs is so performant because it loads all scripts in parallel, regardless of location, and executes them in proper dependency order as needed. To assist with dependency management, a server-side LABjs component is forthcoming. LABjs is ~2.2k when minified and gzip’d.

RequireJS allows you to efficiently load today’s scripts but encourages a modular approach with CommonJS code sharing and nested dependency resolution. The built in optimization tool can reduce the number of scripts that need to be loaded and to minifies the scripts for even better performance. RequireJS allows you reuse your modules in more than one JS environment. RequireJS can be built in a few ways: from the very basic 2.9k version that does not include plugin capability, multiversion and page ready support, to the 6k deluxe version that includes plugin capability, multiversion and page ready support, and the text, i18n, JSONP and order plugins. All sizes are minified and gzip’d.

Whatever your particular needs may be, choosing either loader over plain <script> tags is almost certainly going to be better, not only for your site/application but also for your end users.

 

About the Author

Kyle Simpson is a JavaScript Systems Architect from Austin, TX. He focuses on JavaScript, web performance optimization, and "middle-end" application architecture. If something can't be done in JavaScript or web stack technology, he's probably bored by it. He runs several open-source projects, including LABjs, HandlebarJS, and BikechainJS. Kyle is a Senior Architect for client and server side JavaScript for appendTo, LLC.

Find Kyle on:

About the Author

James Burke is front end developer currently based in Vancouver, BC.

He believes JavaScript is the one true path to a language that is available everywhere, even with its shortcomings. He works for Mozilla Messaging on Raindrop, a web-based messaging interface. Before that, he worked at AOL, improving the speed of Dojo-based web applications like myAOL, AOL Webmail and AIM Chat. He is the core lead for the Dojo Toolkit.

Find James on: