0
votes

I have been reading a bit on RequireJS and I get what it is trying to accomplish. However, there are some things that are unclear to me, maybe you guys could shed some light. I'll list down the questions to make it more readable:

  1. Is RequireJS an implementation of AMD or uses AMD underneath? AMD is a unclear to me. From what I've read, it is an API specification so is it implemented? Can you use AMD even without a module loader like RequireJS? Or is it just a specification.

  2. I've seen this code several times:

    if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
        define( "jquery", [], function () { return jQuery; } );
    }
    

What is the 'define' they are checking? A global object/function? Where did this come from? I'm confused about what define is and how it came about? Is it officially a part of JavaScript?

  1. In a site I am reading, there is a line:

    require(["mustache", "text!template.html"],
        function(mustache, html) {...}
    

There it says: The plugin name and module name are separated by !. I thought the plugin would be mustache but from the sentence, the plugin name is text? Can you explain this syntax?

  1. And lastly, if I understand correctly, RequireJS has a shim to load dependent modules synchronously. Can you give an example of when would I need to do that? I thought that RequireJS async loading of modules would cover all the requirements of loading dependencies since I thought it waits for all modules to be loaded.
1

1 Answers

-1
votes

Programming languages like C, Python, Ruby, etc. all have mechanisms for writing code in self-contained, reusable modules. The JavaScript language has no such feature. Well, not aside from including multiple <script> tags on a web page, which is not a great option for various reasons. Now, if one were to add a module feature to JS, one would need: 1. to write all of one's JS code in an agreed-upon module format 2. a run-time or compile-time library capable of loading or pre-processing modules in that format. Put another way: JS + Module API + Module API library = JS with modules. AMD is the module API. RequireJS is the Module API library.

The essential goal of AMD, of which RequireJS is an implementation, is to define a standard API for writing JavaScript modules.

The AMD API is essentially a single function: define. An AMD module is written assuming that this function has already been assigned to the global variable define. Because JS has no built-in module feature, your only option is to rely on the existence of such a function a priori, in the same way you write browser code with the expectation that variables like document and location exist. You define an AMD module by passing identifiers for your module's dependencies and the code for defining your module to define. define is overloaded to receive this information in various formats, which are covered on the RequireJS API page.

Now that we have the basics out of the way:

  1. The former. AMD is an API specification for JavaScript modules. RequireJS is a library which implements AMD. The Why AMD? page on the RequireJS site elaborates on this relationship.
  2. This is a snippet from the "universal module format." It's a way of supporting multiple JavaScript module APIs at the same time (AMD is not the only format). The idea is that, through introspection, you detect which module API is available, and then use the one you find. If you see that there's a global function named define, you use AMD (the define.amd property is sometimes used to disambiguate this from other module APIs which might use a define function). Similarly, if you see that there's a global module variable, you might use CommonJS. Many scripts assign a global variable to window as a fallback.
  3. Actually, two modules are being imported here. One is mustache. The other is text!template.html, which is a sort of pseudo-module formed by applying the text plugin to the file template.html. The effect is the same as if you imported a regular AMD module which exports the contents of template.html as a string.
  4. Quite simply, you use it when you want to import a JavaScript file which has not been written in the AMD format :). Not all library authors take the time to write AMD support into their modules. Many older scripts which are written purely for browser-side use only assign a global variable to window. In order to import such a script AMD-style, you need to modify its source code to conform to the AMD API. RequireJS's shim feature does this for you automatically.

A competing JavaScript module API is CommonJS, which is the API that Node.js modules use. AMD is supposed to be more browser-friendly, but you might be interested in reading the Browserify project's take on JS modules, which brings up some excellent points. Browserify is essentially a competitor to RequireJS. Where RequireJS uses AMD and is a run-time tool, Browserify uses CommonJS and is a pre-compilation tool.