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

multiple loaders per same page #70

Closed papirosko closed 12 years ago

papirosko commented 12 years ago

I'm developing widget, which used curl.js to load dependencies.

The main widget script containes curl.js code in the begining of the file, then curl() is invoked to load dependencies, after that the initialization is invoked.

My dependencies are in amd format - they are wrapped in define().

No somebody injects my widget into his page. If he uses no amd compatible loader, then everything is OK. But what will happen, when he uses his own version of loader? I suppose there will be name collision for "define()" function.

The best way to resolve this, I think, is to add option to inject "define()" to by custom object, not to "window" object, like it is done with 'apiName' and 'apiContext'. Something like this:

var defineContext = userCfg['defineContext'] || global;
define = defineContext['define'] = function () {
        var args = core.fixArgs(arguments);
        _define(args);
    };

Now I can inject "define" to mine context (e.g. myCtx), and wrap modules with:

myCtx.define("module", function() {} );

unscriptable commented 12 years ago

Hello @papirosko! This makes sense and seems very easy to add. I'll add it to the next release.

For now, you can do something like the following code somewhere in the page before loading or defining modules:

myCtx.define = define;

-- John

unscriptable commented 12 years ago

I pushed a version to the defineContext branch that has two new config properties:

cfg.defineName {String} the property name of `define`, default == 'define'
cfg.defineContext {Object} the object on which to define the property, default == `window`

// example config:
myWidget = {};
curl = { defineContext: myWidget, defineName: 'defineModule' };

// example module:
myWidget.defineModule(function () { /* this is my module */ });

I just realized that by moving the define from its usual location, you can no longer use any of curl's built-in modules such as plugins and shims unless you fork them and modify their defines. Third-party modules would be useless, too. I am going to think about this a bit more before I push this to the dev branch. I wonder if there's a better way.

papirosko commented 12 years ago

yep, you are right.

I took you js-compiled version, and these are the substitutions I've made:

var cmDom = {};

var curl = {
    baseUrl: cm_jsRoot_pr,
    apiContext: cmDom
};

/**
 * M=r.define=function()
 * ->
 * M=cmDom.define=function()
 *
 * define("curl/domReady"
 * ->
 * cmDom.define("curl/domReady"
 *
 * define("js",
 * ->
 * cmDom.define("js",
 *
 * define("domReady",
 * ->
 * cmDom.define("domReady",
 */
var q=!0,y=!1;
(function(r){function i(){}function w(a,b){return 0==N.call(a).indexOf("[object "+b)}
...
unscriptable commented 12 years ago

This issue is related to https://github.com/cujojs/cram/issues/2

papirosko commented 12 years ago

also notice, we must check the existance of 'curl' and 'define' on context before injectoin, and do not override existing one.

This will help to share curl instance between several widgets

unscriptable commented 12 years ago

defineContext, defineName are in 0.6.3