-
Notifications
You must be signed in to change notification settings - Fork 216
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
Uncaught Error: define() missing or duplicated #256
Comments
Hey @jdalton! tl;dr: curl.js expects a named module to use its true name. There are no single-word module names in a package. All module names in packages take the form "[package-name]/[module-path]". Underscore is a collection of things all shoved onto one, large module. It is not truly a package. Since underscore is not actually a package, you shouldn't use a package descriptor to configure it. If you use a "paths" configuration descriptor, it will work. Some background: there are two general types of transformation in AMD: id transforms and url transforms. (I like to call the latter "path transforms" since they could also be performed on file system paths, not just urls.) Path transforms are useful for describing where things are located. ID transforms can be used for a few useful things, including the resolution of the convenient, short-form main module name of a package. I'll use when.js as an example. The package is named "when", but the main module is actually named "when/when". If you type // this is inside module when/node/function
when = require('../when'); According to the CommonJS and AMD rules for name normalization, "../when" should resolve to "when/node/../when", which collapses to "when/when". (I can provide detail on the name normalization, if you like.) By this, you can infer that the when/node/function module is looking for a module named "when/when", not "when". For historical reasons that I missed, folks apparently didn't want to force devs to write Side note: AMD package descriptors define both types of transforms. The "location" property defines the path transform that will be applied to all modules in the package. The "main" property describes the id transform that will happen when somebody decides to use the convenient, short-form name of the package's main module. I'd argue that underscore isn't a package. It's a module wherein all of it's bits are shoved onto a single object. Perhaps one could envision it as a package with exactly one module. However, if it's a package at all, then curl.js requires that its modules be named "[package-name]/[module-path]". If you envision underscore as a module, then you could use a "paths" configuration descriptor instead of "packages" and it should just work in all of the loaders. Apparently, both dojo and RequireJS have logic to accommodate these single-module-packages-masquerading-as-just-a-module things. I looked into providing similar capabilities a few years back and concluded that it could cause problems for multi-bundle, multi-version application development (iow: apps that fetch multiple bundles and could potentially have multiple versions of a package -- such as lodash or jquery -- in these bundles). I've been working on this multi-version stuff lately and am using a solution that seems like it would be immune to this problem. Still, I am hesitant to add more special-case logic into an already convoluted part of AMD. If you've read this far, then I'm really interested in your feedback. Thanks for posting this issue. -- John P.S. Names modules suck for many reasons. |
True, but Underscore now uses it. Testing before worked with unnamed modules for both single file and collections using packages. The unit test file works with both depending on the path passed to its query string. I used I'm curious why the unnamed flavor works as single files with a |
Oh snap. That's idiotic.
So, you're using
Because when the module is anonymous, the loader assigns the name. In this case, that name is "underscore/underscore". :) |
Wow, I typoed hard on that one. I've been using packages because they worked for both single file and modules and didn't require any additional juggling on my end. |
The |
Ok, reopening. :) I'm seriously confused, dude.
What do you mean by "both single file and modules"? Maybe you could paint a precise picture of what you want to do? Can you point me at some source code? Thanks. |
Sorry, I haven't eaten or had coffee yet, my brain is mush ☕ 🍰 I mean I use them for things like |
My config look something like 'packages': [
{
'name': moduleId,
'location': locationPath,
'main': moduleMain
}
] and allows testing for both monolithic builds and modularized builds by passing query params to the test page. |
As much as it pains me to add more special-casing for your situation (and another that @phated encountered in cram.js builds a few weeks ago), I think I have to bite the bullet in order to plug an AMD abstraction leak. Ick. Oh well. The fix will allow the true name ("underscore/underscore") as well as the shortcut name ("underscore") to work in builds and when the non-modular version of lodash is declared as a package in an AMD config. I'll have a fix released in couple of days. Does that work for you? -- J |
Sorry if that comment made it sounds like this is a lodash problem. It's not. It's a combination of the looseness of AMD and its recommended pattern for backwards-compatibility for legacy libraries (or curl.js's lack of completely implementing this pattern). |
No worries. That works for me. In the meantime I've modified my test page to detect, based on the query string, if its a modularized or monolithic build and either add packages or paths configs. |
I'm experimenting with making the lodash.underscore.js build use a named module:
define('underscore', function() { return lodash; });
I'm using a package config to work with amd modules and single files.
I noticed if I used the config of:
I get
Uncaught Error: define() missing or duplicated: ./../dist/lodash.underscore.js
.The Dojo and RequireJS loader both work.
The text was updated successfully, but these errors were encountered: