Skip to content

Add AMD registration as an option.#688

Closed
jrburke wants to merge 4 commits intojashkenas:masterfrom
jrburke:optamd
Closed

Add AMD registration as an option.#688
jrburke wants to merge 4 commits intojashkenas:masterfrom
jrburke:optamd

Conversation

@jrburke
Copy link
Copy Markdown
Contributor

@jrburke jrburke commented Oct 25, 2011

Uses a common factory function with adapters for CommonJS and default browser env to register appropriately based on the environment.

I placed the define() call on the same line as the function(define) { so that a level of indent in the backbone.js code would trigger a noisy diff. However, I can place it on its own line and do an indent of the code if that is preferred.

I also have an optamd-withtest branch that has a test-requirejs.html file showing it working with an AMD loader. I also tested the code in Node, doing a simple test with a Backbone.Model. I did not commit that Node test since it was just a simple code check.

Backbone probably does not want the test page, so I just put the core registration changes in this pull request branch. However I have no problem merging in the test page if that is preferred. The test uses underscore 1.2.1 and jQuery 1.7rc1, which both call define() to register as AMD modules.

Related to Issue #684, where it highlights the usefulness of this patch. Also see the similar ticket for underscore. In short, AMD registration is useful because:

  • It encourages modules for use in the browser in a way that does not require dumping globals.
  • Since dependencies are string names, alternate implementations can be swapped in. For Backbone, it means it can ask for 'jquery' but have zepto loaded instead. It avoids the need for a script like Backbone to have to know of all the scripts that could be used instead of jQuery.
  • Because globals can be avoided, it is possible to build contained libraries. Even ones that do not use an AMD loader, but just the API to connect its individual components. The almond AMD shim can be used for those cases.
  • noConflict() is not enough due to timing issue of script execution and script onload callbacks for dynamically added scripts in IE. For building contained libraries, use of noConflict() for all the modules becomes unwieldy.

Uses a common factory function with adapters for CommonJS and default browser env to register appropriately based on the environment.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there any way to break out this define function? putting it inline seems weird to me.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tbranyen, here is alternate path that could be taken for the patch. It still means passing a function into an anonymous, immediately executed function, but it may be aesthetically pleasing:

    (function (factory){
      var root = this,
          previousBackbone = root.Backbone;

      if (typeof exports !== 'undefined') {
        // CommonJS
        var $;
        try {
          $ = require('jquery');
        } catch (e) {
          // ignore, it is ok in node if it fails.
        }
        factory(root, previousBackbone, exports, require('underscore'), $);
      } else if (typeof define === 'function' && define.amd) {
        // AMD
        define('backbone', ['underscore', 'jquery', 'exports'], function (_, $, exports) {
          factory(root, previousBackbone, exports, _, $);
        });
      } else {
        // Browser globals
        factory(root, previousBackbone, (root.Backbone = {}), root._, (root.jQuery || root.Zepto || root.ender));
      }
    }(function (root, previousBackbone, Backbone, _, $) {
      //Backbone code goes in here
    });

If you would rather see this approach taken, I'll do a different branch with this approach today.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went ahead and did a branch that uses this different registration approach, you can do the compare here. It passes the tests, including the simple node one and the requirejs-based one I have in a test branch.

If you prefer I do a pull with this new optamd2 branch instead of this pull request, then I will close out this pull request and open another with that branch.

@jdalton
Copy link
Copy Markdown
Contributor

jdalton commented Nov 1, 2011

You should avoid var root = this in case this file is concated with another in strict mode

@jrburke
Copy link
Copy Markdown
Contributor Author

jrburke commented Nov 1, 2011

Thanks for the catch, fixed by calling initial setup with global this in this commit.

@jrburke
Copy link
Copy Markdown
Contributor Author

jrburke commented Nov 2, 2011

This pull request is obsolete, see #710 instead.

@jrburke jrburke closed this Nov 2, 2011
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants