Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RequireJS compiler compability broken #32

Closed
antris opened this issue Sep 22, 2011 · 11 comments
Closed

RequireJS compiler compability broken #32

antris opened this issue Sep 22, 2011 · 11 comments

Comments

@antris
Copy link

antris commented Sep 22, 2011

Bonzo defines itself to RequireJS as an anonymous module. The RequireJS library (require.js), when requiring the modules from separated files, takes the module name from the file name and it works perfectly. However, the compiler is dumb, and it cannot detect bonzo's module name from the filename because the define() call isn't in the beginning of the file.

This change makes bonzo pass the module name to RequireJS manually, fixing the problem:

diff --git a/src/bonzo.js b/src/bonzo.js
index 99e66d5..b5dc08a 100644
--- a/src/bonzo.js
+++ b/src/bonzo.js
@@ -1,5 +1,5 @@
 !function (name, definition){
-  if (typeof define == 'function') define(definition)
+  if (typeof define == 'function') define(name, definition)
   else if (typeof module != 'undefined') module.exports = definition()
   else this[name] = definition()
 }('bonzo', function() {
@ded
Copy link
Owner

ded commented Sep 22, 2011

cc @rpflorence

@ryanflorence
Copy link
Contributor

Yeah, I just ran into this also. Been meaning to connect with @jrburke about it.

@ryanflorence
Copy link
Contributor

I think this is a sound solution though (for now at least), then you can simply require(['bonzo'])

@jrburke
Copy link

jrburke commented Sep 22, 2011

The requirejs optimizer tries not to step on any define() that may be declared as part of some non-AMD code, so it only matches for very specific signatures. In this case, it wants to see a function literal in the define call. This signature works best:

if (typeof define == 'function' && define.amd) define('bonzo', [], function () { return definition(); })

The string literal is in the define function so that it is clear this is a named module, and that the optimizer does not need to generate a define call with that name. Defining a named module also works best if this code is optimized by other concat tools but then loaded in a page in a way that does not use an AMD loader, but an AMD loader does exist on the page. In that case using an anonymous call to define will probably result in an error since the module cannot be tied to a module name.

The optimizer will avoid processing the define() call if the name is a variable, in case this is an app-defined define(). Similar reason (but for runtime) for changing the define test to include define.amd. However, if you prefer to accept the risk calling a non-AMD define(), that && define.amd can be removed.

@antris
Copy link
Author

antris commented Sep 22, 2011

Oh, and I forgot to mention that this problem also affects at least the qwery library.

@ded
Copy link
Owner

ded commented Sep 22, 2011

nearly all my modules use the exact syntax shown here already in Bonzo. So if it's a problem, I'd have to fix them all. So I mostly want to double check that this would be the exact syntax we want.

@jrburke
Copy link

jrburke commented Oct 8, 2011

I have updated the requirejs 0.27.1 (the latest release) optimizer and relaxed the define matching a bit to allow for smaller code patterns, so this should be sufficient:

Pattern 1:

    if (typeof define == 'function' && define.amd) define(name, definition)

However, since the optimizer does not know what name is, will add an extra define('bonzo',...) to the built file indicating that 'bonzo' has in the optimized layer, but the above works and is minimal impact on the bonzo source.

If you prefer to not have the extra built code inserted, then this pattern is the recommended one:

Pattern 2:

    if (typeof define == 'function' && define.amd) define('bonzo', function(){return definition()})

I have also been working out suggested syntax for universal modules, but that may be seen as too much change.

So, use Pattern 2 unless the aesthetics of it bother you. In that case, use Pattern 1.

@ded
Copy link
Owner

ded commented Oct 9, 2011

thanks @jrburke i'll go with the first. it looks sexier.

@mattandrews
Copy link

Not sure if this is directly related to this issue, but I'm having issues when using bonzo with requireJS. When I pass bonzo as an argument to require's callback function, it outputs null when I run console.log(bonzo), but if I rename the argument to _bonzo_ or something, my call to console.log(bonzo) returns the correct object.

This could be due to the way I'm using require() -- I map my URLs using require's config/paths tool, so call bonzo like this:

require(["bonzo"], function(bonzo) {
    console.log(bonzo);
});

Anyway: am I wrong, or is Bonzo?

@ryanflorence
Copy link
Contributor

Bonzo is checking if define is 'function' instead of 'typeof define', making a pull request real quick.

@mattandrews
Copy link

Thanks for this -- can confirm that it fixes my issue above.

@ded ded closed this as completed in 8987ebf May 23, 2012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants