A balance between AMD and vanilla JavaScript

My environments tend to be the most productive when I combine global variables with AMD modules and that bugs both the AMD crowd and the vanilla crowd.

I’m not shy about proclaiming my love for requirejs and AMD-compatible JavaScript modules, but sometimes they can suck the life out of me, too. I flip flop between wanting libraries like jquery and underscore as modules without global namespaces and then just wanting them available anywhere, at any time. On the one hand, they are used often and having to define them as dependencies is just an extra annoyance for something that should be considered convenient, and on the other hand you lose what modules actually are dependent on.

I also alternate between wanting to specify exact dependencies for each model vs depending on a module aggregator but then it ends up requiring you to depending on even more modules and the way to actually define those in AMD is kind of frustrating.

I can do write dependencies the commonjs way:

[cc lang=’javascript’]
require(function(require){
var Klass = require(‘Klass’);
});
[/cc]

Or the AMD way

[cc lang=’javascript’]
require([‘Klass’],function(Klass){
// Klass passed in as argument
});
[/cc]

Both ways require duplication. The CommonJS method requires you to build a series of variable definitions with function calls and the AMD method requires you to duplicate identical words and also maintain appropriate order.

If you end up defining every template or model you need for a module then you can get some lengthy dependencies. Anything over 4-5 dependencies becomes cumbersome to manage. When you explicitly add jquery & underscore to that dependency list then you only have 2 or 3 more modules you can really deal with happily and that’s not enough.

I wrote a quick grunt task (located on github: grunt-require-dir) to bundle up a directory of arbitrary files to a single file composed of require calls, allowing me to deal, at least, with dependencies based around subject. This allows me to automate the bundling of directories like templates or models into a single “aggregator” or “accessor” module. This removes my ability to know exactly what is dependent on what, but it provides greater flexibility to refactor and starts to bridge the gap (for me, anyway).

I’ve also started to think of jQuery, underscore, and Deferreds as features that are just part of my environment, essentially labeling them as global dependencies and having my modules use them as global variables. So sue me.

It’s also interesting to note that, with AMD and requirejs, your global namespace is significantly more pristine. So why avoid it? Why not have first class features of your application or framework occupy that space now? It’s not poisonous and provides loads of convenience. Use AMD where it benefits you and ignore it when it doesn’t.

One thought on “A balance between AMD and vanilla JavaScript”

  1. Why the anal attitude towards globals anyway which leads to the AMD evangelists?

    JavaScript, the DOM and browsers themselves expose numerous globals. So what if jQuery occupies one global and my application occupies another? This is how JavaScript in the browser works.

    People do realize when they use an AMD loader they are simply using that loaders’ global variable and namespacing their modules under that? Sure you can “optimize” into a single file, wrap with an IIFE AND have the loader inside the IIFE so everything is scoped within that anonymous function, but that could easily achieved using normal object namespacing and some build proccess.

    Simple fact of JavaScript, you cannot have code spread across multiple files without having at least one global variable to tie them together, unless you use eval.

Leave a Reply