In the part one of this article we’ve looked at the way RequireJS helps structure an application in javascript. But there is more to it then that. RequireJS is a pretty recent tool in a landscape dominated by big players like jQuery, Prototype and YUI. Unlike all of these, RequireJS is a single purpose tool. And there’s a lesson to be learned from that.
YUI 3 vs RequireJS
Another library that does asynchronous module loading is YUI 3. It has a use() method, which will also asynchronously load scripts and then invoke a callback function. The architecture of YUI 3 seems to be less insistent that you create your own modules and load them using the tools YUI uses for it’s own modules. This can definitely be useful if you’re less interested in the whole async loading / dependency handling thing. But perhaps I can convince you that this might not be the right way to go.
In YUI 3 if you do want to use the module approach, you’ll have to create a YUI module, which will of course create a dependency on the core of the YUI library. This dependency creates a risk. What if the YUI team tomorrow decided to move to a different architecture? This problem doesn’t exist with RequireJS. It is based on open specifications, so you know they won’t change. And because it’s only purpose is to load your modules in the right order, there won’t be any future versions with new modules other scripts on the page might depend on. So you won’t have conflicting versions of the software running on the same page.
A big problem in Javascript today, as I’ve mentioned in part one, is the global. Libraries try to solve this by putting all their functionality as properties on a single global object. An asynchronous loading solution releases you from this problem. However because YUI 3 is still stuck on the ‘everything is a property of a single global’ paradigm, their architecture insists every module must still be hooked up to this centralised object. So even if your script needs to distinct parts of the application, you will only get one, and have to pull the bits off that Y object yourself. Which looks like this:
YUI().use('cookie', 'animation', function (Y) {
Y.cookie;
new Y.Anim();
});
In the CommonJS async module used by RequireJS, that code will look like this:
require(['cookie', 'anim'], function (cookie, Anim) {
cookie.eat(); // this makes much more sense
new Anim();
});
Minimising
Now it must be said that RequireJS comes with it’s own minifier. This tool can merge the different files in your application and compress them. So that in your production environment all your code can still be pulled in a single request. This might be useful for performance, although downloading six small files simultaneously can be a lot faster then downloading a single big one.
Minifiers work by removing white space and comments, and by replacing variable names with shorter ones. This last one can only work if the variable isn’t in the global, or a property of some object. Because RequireJS stays away from the global, and doesn’t rely on a single object with modules as properties, the code you write for RequireJS can be compressed quite a bit more then you would get out of most scripts.
Design patterns
I first started using RequireJS when writing Jengin, a Javascript game engine I’ve created for a game in the Mozilla Game On challenge.. I’ve spent a lot of time looking for effective ways to utilize the flexibility of javascript, without getting caught in one of it’s snares. Using RequireJS, and a few design patterns Javascript can be used to create object oriented programs, without extending native objects and without complex libraries to create classes and inheritance in your application. *caugh*Prototype*caugh*
I’ll be writing more about these patterns in the future.
In conclusion
NodeJS and other javascript servers have brought us a new insight into the javascript language. Given the right approach, javascript can be a very powerful and effective tool. RequireJS does not simply provide a way to handle script loading, it creates a structured way to build complex applications by utilising the good parts of javascript, and avoiding the bad. And it is most definitely a tool worth looking in to.