why amd #22

paulmillr opened this Issue Jun 25, 2012 · 14 comments

4 participants


and ain't commonjs?


AMD is the most flexible and appropriate module definition for the browser. If you use CommonJS, or anything else synchronous, you ultimately have to wrap your code in something that looks like AMD to prepare it for use in the browser. What I'm saying is, let's standardize that pattern, call it AMD, and move on. That way you can write it however you like and the build steps are up to you.

So feel free to write your code as CommonJS and run some build tool to prepare it for the browser, but AMD is the most sensible target for that build tool to be aiming for.

If you'd like to discuss in more detail then please move this to the mailing list, since it's not a bug report or feature request. http://groups.google.com/group/jamjs

@caolan caolan closed this Jun 25, 2012

Sure, i'd discuss this more.

Also, every time I see mailing list in 2012, my face is like this. Could you please consider using something like OST.io?


I also don't get that vibe around AMD. I code mainly for browser and I do CommonJS modules, why should I add complexity like AMD to my website, I quite don't get it, with CommonJS it's much simpler and modularity is way much better.

Currently I'm working with strictly client-side application that's build from over 200 modules from 14 packages, doing that with AMD would be much more hassle.


@medikoo do you have to build your javascript every time you want to open the app in the browser? Or do you use some CJS loader?
Why do you say AMD is more complexity? Using Common JS and AMD is pretty much equivalent, except AMD comes with more goodies and is better natively supported by browser. I'm also working on a client side app with over 200 AMD modules, why would you think CJS is better modularity?
The package part is what I'm trying to figure out now. How do you pull in other packages as dependencies? Do you use a custom script for that?



  • More shittier for debugging: when you run require('module') in browser console, it will throw an error. And the error trace seem to be lost because of onerror shit.
  • AMD by default sends ajax requests when you call require and module isn't present in cache. The whole "one module per file and ajax loading of them" is bullshit and terrifically inefficient. Of fucking course everyone joins their files in production, but where's the hell advantages of AMD then if same can be done with commonjs? Yea it's slightly easier in development env, but only until build tools will support source mappings.
  • The implementation size of amd / requirejs is 77k. lol fukken wat? Module loader is the simplest thing, why the fuck should it be 77k? As compared, zepto.js, which copies the whole jQuery API is 47k (!!).
  • CommonJS modules work are native to node.js which means you can use your files in node, for example, for testing without browser.
  • Shitty syntax. You need to write something like this in every file:
define(['dep1', 'dep2'], function (dep1, dep2) {
    //Define the module value by returning a value.
    return function () {};

instead of

var dep1 = require('dep1');
var dep2 = require('dep2');

@KidkArolis as for

do you have to build your javascript every time you want to open the app in the browser

I'm using brunch which automatically rebuilds the whole app every time. You can look at example app structure here: https://github.com/paulmillr/brunch-with-chaplin/tree/master/app. Yep brunch comes with commonjs support which is done in ~70 lines of code.


@paulmillr I'm not saying you should write your code in AMD, I'm saying whatever build tool you're using should produce AMD because it's the most flexible format and has a bunch of useful tools. It's already producing something that looks like AMD anyway.

Also RequireJS is 17kb minified, 6.2kb gzipped, not "77kb". Remember, that still gives you all the power of dynamically loading modules etc. If you don't need that and want just a basic loader (like the one you're using for your compiled CommonJS modules) just use the --almond flag when doing "jam compile" and it will use the almond loader instead. This loader works only for bundled modules and is 1kb minified and gzipped.

By doing this you get all the extra functionality of AMD and it's plugins. You can inter-mix AMD, CommonJS and even Harmony-style modules with legacy browser global style code. You can run coffeescript, fetch templates and pre-compile them. Automatically detect the modules from dependencies you're actually using (not just the ones you have installed). And combine all of these into a single optimized download.


@KidkArolis as for packages, I would recommend you install them once and just add them to your git repository. You don't need to compile 'native' extensions like you may need to with Node modules, so there's really no reason to avoid shipping them with the rest of your front-end code.

That said, you can use jam.json as an install argument if you like "jam install path/to/jam.json" would install all the dependencies in jam.json. I don't expect people to use this very often, because I suggest you keep them in your git repository.


@caolan precompiling coffee & templates is done instantly via build tool and auto-wrapped in module.

Okay, issue with size is irrelevant. And still what about debugging hell? There's no freaking way to instantly detect line number where require() error happened, unlike in simple commonjs sync loaders. What about using ajax "by default"? Can this be disabled? I don't want app to make ajax requests every time module wasn't found in cache. As I understand, AMD is a standard, maybe there's something better than shitty requirejs that fits standard?


I haven't had any problems with debugging, where exactly are you running into issues? Remember that when loading modules not compiled into a single file it's actually just inserting a script tag to load them, not doing AJAX and eval(), so debugging will work as normal. It does use AJAX if there is a compilation step (coffee-script), but then it's up to the compiler to provide you with meaningful errors regarding the source language (as always).


Oh, and when it is compiled, debugging will work as it does with your current system.

  • can't say I have problems with debugging
  • the "loading each file via ajax" argument doesn't make sense, because you obviously build for production
  • I'm sure you can do testing without the browser with amd
  • I like the syntax. I'd argue that returning the module value is more intuitive than setting module.exports.

It's interesting that we basically can't name any real advantages/disadvantages/differences of AMD and CJS :-/

Require.js site has a couple of good ones:

  • Dynamic code loading
  • Loader plugins again are arguably less magical and more intuitive than precompiling Another awesome one is
  • Support for non amd JS via shim config

@KidkArolis I agree that being able to load non-AMD code is perhaps the most important part, especially when choosing a style to standardize on for packages.


@KidkArolis I use modules-webmake, when binded to server it works transparently (no extra action needed on your side for rebuild), it also supports sourceMaps so in browser's developer console you can work with each module file as separate instance. If you don't like server approach, you can also with help of grunt configure task that will rebuild bundle on each file change.

The biggest problem I see with AMD which is also a reason for it's complexity, is that it addresses two different problems as one:

  1. Modules for JavaScript
  2. On demand dependency loading in browser.

Those are two different things. JavaScript modules are usually much smaller than static files you'd like to load in a browser, and as long as loading hundreds of files asynchronously is noticeably slower than loading a few, as long merging those two issues won't make sense.
If you take a look how big heavy JS websites work, you'll see that on demand they load bundles of modules (and not each module separtely), that's how e.g. Google Plus or Facebook works. Facebook uses CommonJS modules builder modulr, they pack modules into bundles and load that bundles on demand.

AMD introduces boilerplate (define function wrapper) which is first sign that something is not right. We should be able to write our code as simple as it's with CommonJS, where we can just start our files with var local and don't bother with extra wrappers. It should be simple as that, no exceptions.

AMD doesn't work with natural file system structure, it tries to fix that demanding extra configuration file, which is just another complexity we don't need.

To process bundled CommonJS modules in browser you need to add only extra 60 lines of code, while processing AMD needs over 2000 lines of extra logic.

In my opinion CommonJS/Node.js modules greatly resolve problem 1, mind also that choosing this style, you're choosing style that's already used in server-side JavaScript, so you don't need any extra hacks to run your code in Node.js

Concerning Problem 2, first check if you really have such big application that can noticeably benefit from that, if so, then use dedicated tools that address just this problem and doesn't force you to reorganize your application structure or change its code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment