- However, the format is unfriendly to browser context, and it’s impossible to implement the loader 100% correctly.
- In the browser, people ended up using AMD format instead. Also, AMD try to incorporate CommonJS format by introducing special dependency names; see the 3rd and 4th paragraph of the spec.
For years, a lot of discussion on the difference of the formats surrounds the sync v.s. async nature of the format. jrblake, the author of the AMD spec and require.js, have already explicitly explain his argument on why he disagreed with the trade-offs made in the CommonJS module format.
However, I still ended up drawing the conclusion of my research — as of 2013, CommonJS modules is more welcomed to the developers than AMD modules. But why? In my humble opinion, of all the differences in design between CommonJS module and AMD module, this one stands out and made the difference: CommonJS module spec requires one scope per module. This in turn gives CommonJS modules the following behavior:
- Every module get a private scope, for free — the only things expose to others are the ones you explicitly expose in the
- In return, module scripts don’t get to access the globe object of the main context — e.g. the
window object in browsers. This has significant implication — module scripts can never take global APIs for granted — one would have always explicitly
require() for it. On the other hand, one could never mess up with the dependency system by attaching fake fake APIs on the global object — everyone has to be honest to the dependency tree, and the loader.
- Without the global object, native APIs available to the module would also need to be
- Limiting one file per module is pretty much an outcome of the scope design. It will be really hard to define scope syntax, to house multiple scopes within one file, and it will be even harder to implement.
- Same applies to sync dependency loading. If modules are loaded in their own scope, they could surely block the execution of requestee.
- Lastly, and sadly, one of the drawbacks of the one scope per module design: you can never ever simulate private scope in the browser reasonably. One could surely wrap CommonJS module into a function scope, or simulate sync loading with sync xhr and
What does all that means
What is broken, for modern day needs, is the browser context, not AMD, which tried really hard to address it. What AMD proofed is that we need new language feature, or browser APIs, to cope what we are facing. Hopefully, the new ECMAScript Harmony module is being worked on in Gecko and will be landed soon. How Harmony module could deliver the promise is not the scope of this article; it would be a further pending research topic for me.
It also limits people writing heavy client-side web applications — people is currently prevented to split their apps into modules agnostically of any frameworks. This is worse than PHP, in which the frameworks have already start working together on common standards, i.e. PSRs.