cujojs / curl

curl.js is small, fast, extensible module loader that handles AMD, CommonJS Modules/1.1, CSS, HTML/text, and legacy scripts.
https://github.com/cujojs/curl/wiki
Other
1.89k stars 216 forks source link

Uncaught Error: Multiple anonymous defines encountered #243

Closed thomaswhite closed 10 years ago

thomaswhite commented 10 years ago

I am migrating a set of plain JS modules to AMD and I am having fun. At one point I started receiving an error "Uncaught Error: Multiple anonymous defines encountered" and I am stack. I switched to the debug version of curl and I can see the error is not consistent with one specific file - when I reload the page the error can be for one or another js file. I use jQuery version of the recent curl from the dist folder.

This is my code:

       curl.config( {
              "baseUrl" : "/js",
              "paths":{
                      "amd":        "js_amd",
                      "cdnjs":      "//cdnjs.cloudflare.com/ajax/libs",
                      "jquery":     "//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.js",
                      "moment":     "//cdnjs.cloudflare.com/ajax/libs/moment.js/2.4.0/moment.min.js",
                      "dustjs-linkedin" : "dust-core-2.2.2.min.js",
                      "dustjs-helpers"  : "dust-helpers-1.1.1.js",
              }
          });

          curl( ['amd/debug', 'amd/socket-io' ], function(debug, socket){
                     debug.log( 'socket-io loaded.');
                 })
                  .next(['amd/debug', 'amd/tiny-pubsub', 'jquery', 'amd/pages', 'amd/main', 'amd/local-content', 'dustjs-linkedin', 'amd/add-dust-helpers' ], function (debug, tiny) {
                      debug.info('Pages and main ready.');
                      tiny.pub('page-init');
                  })
                  .next([ 'js!/templates/all.js'])
                .then(
                      function () {
                         debug.log('Ready.');
                      },
                      function (ex) {
                          throw ex;
                }
          );

Any ideas?

unscriptable commented 10 years ago

Hello @thomaswhite,

The answer to this problem is likely inside your files that you've converted to AMD. Be sure that each file contains exactly one define() and that it is not named (it should not have an id as the first parameter).

Your configuration looks good, except for a few minor points:

  1. Do not put the ".js" at the end of the paths. Modules are not allowed to end in ".js", although curl.js is forgiving of this in most cases.
  2. .next() is deprecated and unnecessary in curl 0.8+. If your modules each name their own dependencies, then you should not need to sequentialize the loading using .next(). If you are still using scripts (instead of modules), then take a peek at the legacy loader (curl/loader/legacy).

-- John

thomaswhite commented 10 years ago

John,

Thank you for your help.

I followed your instructions and now the code loads and works (using legacy loader and making sure all other modules use 'define' function in expected way). Unfortunately I still see the same error randomly when I reload the page.

It seams is some sort of a timing/caching issue. If I disable the cache (in Chrome dev tools) the error never appears.

Where shell I start from?

Thomas


Thomas White

Mobile:+44 7711 922 966 Skype: thomaswhite gTalk: thomas.0007 http://www.linkedin.com/in/thomaswhite0007 http://www.facebook.com/thomas.0007

On 9 December 2013 14:56, John Hann notifications@github.com wrote:

Hello @thomaswhite https://github.com/thomaswhite,

The answer to this problem is likely inside your files that you've converted to AMD. Be sure that each file contains exactly one define()and that it is not named (it should not have an id as the first parameter).

Your configuration looks good, except for a few minor points:

  1. Do not put the ".js" at the end of the paths. Modules are not allowed to end in ".js", although curl.js is forgiving of this in most cases.
  2. .next() is deprecated and unnecessary in curl 0.8+. If your modules each name their own dependencies, then you should not need to stage the loading using .next(). If you are still using scripts (instead of modules), then take a peek at the legacy loader (curl/loader/legacy).

-- John

— Reply to this email directly or view it on GitHubhttps://github.com/cujojs/curl/issues/243#issuecomment-30137950 .

unscriptable commented 10 years ago

Oh, I just remembered: another thing that can cause this issue is if an AMD module is loaded with a <script> element or with the legacy loader. Be sure that all modules (actually any script that has a define() call in it) are loaded as modules and not as scripts.

unscriptable commented 10 years ago

Feel free to re-paste your new config so I can see.

unscriptable commented 10 years ago

And paste a sample of one of your modules while you're pasting things. :)

thomaswhite commented 10 years ago

Here are the config and the defines

  curl.config( {
          "baseUrl" : "/js",
          "paths":{
                  "amd":        "amd",
                  "links-to":   "amd/links-to",
                  "cdnjs":      "//cdnjs.cloudflare.com/ajax/libs",
                  "jquery":     "//

ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.js", "moment": "// cdnjs.cloudflare.com/ajax/libs/moment.js/2.4.0/moment.min.js", "dustjs200" : "// cdnjs.cloudflare.com/ajax/libs/dustjs-linkedin/2.0.0/dust-core.min.js",

                  "dustjs-linkedin" : "amd/dust-core-2.2.2",
                  "dustjs-helpers"  : "amd/dust-helpers-1.1.1",
                  "dust-templates": {
                          "location": "/templates/all.js",
                          "config": {
                                 loader: 'curl/loader/legacy',
                                 exports : 'dustTemplates=1',
                                 requires: ['dustjs-linkedin']
                          }
                   },
                  "socket.io": {
                      "location": "/socket.io/socket.io.js",
                      "config": {
                          loader: 'curl/loader/legacy',
                          factory: function (fullId) {
                              return io;
                          }
                      }
                  }

// This does not work :-( // "bootstrap" : "link!// netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.no-icons.min.css ", // "font-awesome": "link!// netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css" } });

      curl( [
             'links-to/debug',
             'links-to/socket-io',
             'links-to/pages',
             'links-to/main',
             'links-to/local-content'

            ], function(debug){
                 window.onerror = function(error, url, line, stack,

extra) { debug.error(error, url, line, stack, extra); return true; }; }) .then( function () { console.log('Ready.'); // debug.log('Loaded.'); // do something after the dom is ready }, function (ex) { throw ex; } );

---------- the the bottom of dust-core-2.2.2.js ------

if (typeof define === "function" && define.amd) { define("dustjs-linkedin", [], function () { return dust; }); }else if (typeof exports !== 'undefined') { if (typeof process !== 'undefined') { require('./server')(dust); } module.exports = dust; } ---- at the top of dust-helpers define(['dustjs-linkedin'], function ( dust ) { --- add-dust-helpers --- define(['moment', 'dustjs-linkedin', 'dustjs-helpers'], function (moment, dust, helpers) {

--- local-content --- define(['jquery', 'links-to/socket-io', 'links-to/debug', 'links-to/tiny-pubsub', 'links-to/add-dust-helpers', 'page', 'dust-templates' ], function ($, socket, debug, tiny, dust, page, templates ) {

--- main --- define([ 'jquery', 'links-to/socket-io', 'links-to/tiny-pubsub', 'links-to/debug', 'links-to/detect_bottom' ], function ($, socket, tiny, debug ) { --- debug -- define([], function(){

--- detect-bottom define(['jquery', 'links-to/tiny-pubsub', 'links-to/debug' ], function ($, tiny, debug) {

--- pages define(['jquery', 'links-to/socket-io', 'links-to/debug', 'links-to/tiny-pubsub', 'page' ], function ($, socket, debug, tiny, page ) { --- socket-io define(['socket.io', 'links-to/debug' ], function (io, debug) {

--- tiny-pubsub define(['jquery'], function ($) { --- page.js at the bottom of the file if (typeof define === "function" && define.amd) { define("page", [], function () { return page; }); }else if( typeof module !== 'undefined' && module.exports ){ module.exports = page; } else { window.page = page; }


I think the problem comes from: "dust-templates": { "location": "/templates/all.js", "config": { loader: 'curl/loader/legacy', exports : 'dustTemplates=1', requires: ['dustjs-linkedin'] } },

The error messages stopped when I changed the requires from "dustjs-helpers" to "dustjs-linkedin". May be the problem is present because the legacy file depends on dustjs-helpers which depend on the dustjs-linkedin.

Looking at the debug log the required module is requested early at the beginning of the log by the legacy loader but later the same module is loaded again that throw the error.

Is it possible the module requests initiated by the legacy loader to be some how not registered properly and the main AMD logic tries to load the module again? In this case

Thomas


Thomas White

Mobile:+44 7711 922 966 Skype: thomaswhite gTalk: thomas.0007 http://www.linkedin.com/in/thomaswhite0007 http://www.facebook.com/thomas.0007

On 9 December 2013 22:53, John Hann notifications@github.com wrote:

And paste a sample of one of your modules while you're pasting things. :)

— Reply to this email directly or view it on GitHubhttps://github.com/cujojs/curl/issues/243#issuecomment-30182619 .

unscriptable commented 10 years ago

page.js looks like it may be a problem. From your code snippets, I can't see how it's configured. It's a named module, which means it must have a path mapped to it or it must be at the baseUrl. I don't see a path configured for it.

The exports property of dest-templates looks strange. Seems like you want to use a factory there instead of an exports? https://github.com/cujojs/curl/blob/master/src/curl/loader/legacy.js#L20

Does dust-templates have a define() in it?

May be the problem is present because the legacy file depends on dustjs-helpers which depend on the dustjs-linkedin.

We've tested transitive dependencies pretty thoroughly, so I'm skeptical. :) It might just be a timing fluke that stopped the error. If so, it will come back again.

thomaswhite commented 10 years ago

John,

I have prepared a zip file with all my files which you can use to reproduce some of the problems. I would like to email it privately to you.

Thomas


Thomas White

Mobile:+44 7711 922 966 Skype: thomaswhite gTalk: thomas.0007 http://www.linkedin.com/in/thomaswhite0007 http://www.facebook.com/thomas.0007

On 10 December 2013 17:31, John Hann notifications@github.com wrote:

page.js looks like it may be a problem. From your code snippets, I can't see how it's configured. It's a named module, which means it must have a path mapped to it or it must be at the baseUrl. I don't see a path configured for it.

The exports property of dest-templates looks strange. Seems like you want to use a factory there instead of an exports? https://github.com/cujojs/curl/blob/master/src/curl/loader/legacy.js#L20

Does dust-templates have a define() in it?

May be the problem is present because the legacy file depends on dustjs-helpers which depend on the dustjs-linkedin.

We've tested transitive dependencies pretty thoroughly, so I'm skeptical. :) It might just be a timing fluke that stopped the error. If so, it will come back again.

— Reply to this email directly or view it on GitHubhttps://github.com/cujojs/curl/issues/243#issuecomment-30249054 .

thomaswhite commented 10 years ago

After many tries and re-factoring I still have this error randomly from time to time. I think there are some timing issues that unfortunately have not been covered by the tests.

I fail to understand why we throw an exception and stop the whole process of loading instead of try to recover from the error. Requesting a file that has been already requested is something to be avoided but can be easily recovered.

I love the ideas, the architecture, the packages, the plugin mechanism and the variety of files to be loaded by curl.js. You guys have done a great work. There are just a couple of small things left to be polished. It is a shame not to have the resources to complete such a good work.

I am giving up on curl.js because the random errors do not give me confidence to use it in my projects.

Thomas

manast commented 10 years ago

I am getting the same error and is driving me insane :). The problems seems to be related to the text plugin, as soon as it tries to load the plugin I am getting the error. Seems like it does not like that the plugin itself is unnamed... any tips about what could be the problem?

unscriptable commented 10 years ago

Hey @manast. Can you provide some more context? Perhaps open another github issue, or start a discussion on #cujojs (freenode) or google groups?

manast commented 10 years ago

@unscriptable yes. I will do that. I think that the problem arises when you use a plugin within a define context, but I need to reproduce it in a simple test case:

define([...], function(...){
  curl("text!example.txt", function(example){
    console.log(example);
  });
}

I will confirm this as soon as I have a few minutes.

regards,

Manuel.

mbrowne commented 8 years ago

For anyone else encountering this error in the future, see also https://github.com/cujojs/curl/issues/283.