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.88k stars 216 forks source link

some modules are seen as undefined #262

Closed x-yuri closed 10 years ago

x-yuri commented 10 years ago

Here are the test files:

/index.html:

<!DOCTYPE html>
<html>
  <head>
    <script src="/curl.js"></script>
  </head>
  <body>
    <script>
      curl(['/m1.js', '/m2.js', '/m3.js', '/m4.js', '/m5.js'], function(m1, m2, m3, m4, m5) {
          console.log('done', m1.v, m2.v, m3.v, m4.v, m5.v);
      });
    </script>
  </body>
</html>

/m1.js:

define(function(require, exports) {
    var m3 = require('/m3.js');
    exports.v = 1;
    console.log(1, m3);
});

/m2.js:

define(function(require, exports) {
    var m3 = require('/m3.js');
    exports.v = 2;
    console.log(2, m3);
});

/m3.js:

define(function(require, exports) {
    var m1 = require('/m1.js');
    var m2 = require('/m2.js');
    var m4 = require('/m4.js');
    exports.v = 3;
    console.log(3, m1, m2, m4);
});

/m4.js:

define(function(require, exports) {
    var m5 = require('/m5.js');
    console.log(4, m5);
    return 4;
});

/m5.js:

define(function(require, exports) {
    exports.v = 5;
    console.log(5);
});

And here's the output in the console:

1 Object {}
2 Object {}
3 Object {v: 1} Object {v: 2} Object {}
5
4 Object {v: 5}
done 1 2 3 undefined 5

Everything's as expected, except for the 4th module being seen as undefined.

unscriptable commented 10 years ago

Hey @x-yuri,

curl.js eagerly evaluates factory functions. This means it can't always resolve circular dependencies. I highly recommend you remove the cycles from your dependency graph. They are never necessary and can cause other problems.

If you can't remove the cycles, you should try RequireJS or Inject, which both handle dependency cycles.

I noticed that you are using urls, not module ids, in your code snippet. This is not causing the issue, but could lead to further frustration. We've got a tutorial about module ids. I hope you find it helpful! http://know.cujojs.com/tutorials/modules/consuming-modules-module-ids

Closing this issue, but please continue to comment.

Regards,

-- John

x-yuri commented 10 years ago

Thanks for the feedback. As to using URLs, as far as I remember the only (or main) reason is to be able to add timestamps, like: http://example.com/some/file.js?t=20140101-000000. I don't really trust browsers, caching resources. So I prefer to change URL as soon as the resource changes. Am I being paranoid? Am I doing it wrong? Is there a way to both change URL and use module ids?

x-yuri commented 10 years ago

@unscriptable Also, I wonder if there are cases where curl.js will handle circular dependencies just right to be relied upon. In other words, are there any use cases for circular dependencies with curl.js?

unscriptable commented 10 years ago

Hey @x-yuri,

Regarding circular deps: it is not possible to resolve cycles when loading modules in a bundle. Hmmmm, it might be possible if you use a plugin to load the modules in the cycle. A simple setTimeout might be all that's necessary. I have not tried this, though.

But this change requires that you refactor the code of your modules. If you are refactoring, why not just remove the cycles? :)

Regarding cache busting: this can be easily achieved via a curl shim. I'll post an example shortly.

-- J

unscriptable commented 10 years ago

This is totally untested, but is likely close to what you want for cache busting:

// file name: "myApp/bustTheCache.js" -- should be the same as the id in the define, below:
define(/*=='myApp/bustTheCache',==*/ ['curl/_privileged'], function (priv) {
"use strict";

    var loadScript = priv['core'].loadScript;

    // override loadScript to bust the cache
    priv['core'].loadScript = function (def, success, failure) {
        var buster = '?' + new Date(); // you can devise something better, I am sure!
        def.url += buster;
        return loadScript(def, success, failure);
    };

});

See this google groups thread about a different curl shim we created recently: https://groups.google.com/forum/#!topic/cujojs/sBjjhUZv_DM There are notes about how to use it.

In short: you will want to either build it into your own custom curl.js via the tools in the build/ directory or you will want to preload the shim.

-- J