Search code examples
javascriptrequirejsamdr.js

What does r.js really do?


I'm trying to understand the benefits of the popular r.js.

It seems to...

  • concatenate a list of manually selected JavaScript files
  • uglify/minimize that combined code
  • do some similar stuff for CSS files (combine them)

Also, (what it makes it different from generic combine/minify tools) it seems to...

  • convert Node-style require() modules to AMD style modules
  • name anonymous modules (eg. define(['dependency'], function(){...})
  • offer some support for loader plugins, e.g. inline CSS files

It does not seem to...

  • analyze and automatically resolve dependencies found in files (like, include file foo.js into the package just because r.js finds a define(["foo"], ...)

Is this correct, or did I miss something?


Solution

  • You are wrong, because r.js does automatically resolve dependencies. If you have a main.js file with this:

    define(["foo"], function (foo) {
    });
    

    Then if you ask r.js to create produce an optimized module out of main.js, it will include the code for module foo into the build.

    Some caveats:

    1. It is possible to tell r.js to exclude modules. So if a module you think should be in an optimized bundle is absent, it may be that it has been excluded. (You know how you are using r.js but if you use a bundle produced by someone else and you wonder, then this may be the answer: they specifically excluded a dependency from the build.)

    2. r.js does not find nested dependencies unless you tell it to. For instance:

      define(function () {
          require(["foo"], function (foo) {
          });
      });
      

      r.js won't find that foo is required unless you set findNestedDepencencies to true in your build config.

    3. r.js can find only dependencies that are specified in the form of a list of string placed as a literal in the location where the require and define calls expect dependencies. So if you do:

      define(function () {
          var deps = ["foo"];
          require(deps, function (foo) {
          });
      });
      

      Then r.js won't know that foo is a dependency, because in require(deps, ... your dependencies appear as a symbol reference, not as a list of strings. You would have to specify foo as a dependency manually in the build configuration. There's no flag to turn on to make r.js find these cases.