Ideas for standardizing built AMD files

42 views
Skip to first unread message

Taka Kojima

unread,
Mar 1, 2012, 4:02:19 PM3/1/12
to amd-im...@googlegroups.com
I wanted to start a thread about standardizing built modules format, I'm proposing a solution, but would also like to hear about how other AMD loaders handle built files.

I am thinking that a top-of-file define call, that looks like this, should work pretty well:

define(["some/module", "some/other/module", "some/other/sub/module"]); 

The idea being that if you only specify an array and no other arguments, you are saying "This file provides definitions for all of the modules in this array".

The only issue with the above format is that it breaks use cases of anonymous modules which are arrays that have no dependencies.

The nice thing about this, is that it also allows you to specify multiple named modules per file during the dev process (don't know if this is a common use case, but it's a nice side effect).

Other pros cons?

Maybe instead of define, we do something like:

require.provides(["some/module", "some/other/module", "some/other/sub/module"]); 

I think RequireJS handles this by doing require.pause() at the top of files and require.resume() at the bottom of files, am I right James?

How do other AMD loaders handle built files?

I know we could handle this by essentially calling something like require.pause() at every define call, and require.resume() on the script load events, but that negatively impacts the speed of all other modules that only have one define() call per file.

Eric Bréchemier

unread,
Mar 2, 2012, 9:20:41 AM3/2/12
to amd-im...@googlegroups.com
I think this is related to recent discussions about top-level calls
and anonymous modules:

Document entry point for a multi-module program
https://github.com/amdjs/amdjs-api/issues/8

How to define the top-level module of an application?
https://groups.google.com/group/amd-implement/browse_thread/thread/2fac555d3136b55b

> define(["some/module", "some/other/module", "some/other/sub/module"]);

Calling define() only with an array of dependencies looks interesting,
but it lacks the possibility to trigger a callback for the
availability of all modules.

> require.provides(["some/module", "some/other/module", "some/other/sub/module"]);

Beware that require is not defined at the top-level by AMD
specification, only as a local dependency.

Cheers,

Eric

James Burke

unread,
Mar 2, 2012, 2:31:12 PM3/2/12
to amd-im...@googlegroups.com
As Eric mentioned, we've talked a bit on this before. I favor just
using a global require, but the folks that prefer not to use that,
IIRC, John Hann and Rawld, I do not think have proposed something
else. Using anything on define() seems like the incorrect place, as I
mentioned in that thread that Eric mentioned.

Some requirejs specific notes below…

On Thu, Mar 1, 2012 at 1:02 PM, Taka Kojima <ta...@gigafied.com> wrote:
> I think RequireJS handles this by doing require.pause() at the top of files
> and require.resume() at the bottom of files, am I right James?

No, the pause/resume stuff was in some ancient code. Now any global
require()/requirejs() call triggers the module execution stuff.

James

Taka Kojima

unread,
Mar 2, 2012, 2:55:15 PM3/2/12
to amd-im...@googlegroups.com
There is some overflow into those other discussions, but I was more talking about this scenario:

//someFile.js

define("d", ["a", "b","c"], {something: true});
define("a", {something: true});
define("b", {
something: true});
define("c", {
something: true});

In this scenario, we essentially have to halt all dependency lookup until the final define() call is made. This is somewhat unflexible and leads to lesser speed overall (although in most cases, it will be negligible). It also stops me from doing any sort of async define call in the script.

If we replaced the define call for "c" with the following:

setTimeout(function(){
    define("c", {something: true});
}, 1000);

RequireJS would try to look elsewhere for "c", even though it is defined later on in the file, just not immediately.

d depends on a, b and c, which are defined later in the file, so how else do we solve this? Using existing functionality it could be something like this:

//someFile.js
define(function(require, exports, module){
    require.config({
    paths : {
    "d" : module.id,
    "a" : module.id,
    "b" : module.id,
    "c" : module.id
    }
    });

    return false;
});

define("d", ["a", "b","c"], {something: true});
define("a", {something: true});
define("b", {something: true});
define("c", {something: true});

I don't even know if the above will currently work in RequireJS, but the gist of it is that at the top of every file we say "this file provides definitions for these modules".

It is more code and I was suggesting that we could simplify it into a a single function call with an array like:

define(["d", "a", "b", "c"]); 

Doing something like the above allows us to not halt dependency lookup/fetching at any point the script's execution, and also allows for async calls to define().

This only applies to files with more than one named module definition in them, so in most scenarios these are files outputted by a build/optimization tool. 

This may be viewed as "going backwards", i.e. AMD loaders already work with multiple named define() calls in them (that depend on each other), without any extra code, but I believe this approach definitely has some pros to it.

Taka

James Burke

unread,
Mar 2, 2012, 4:30:24 PM3/2/12
to amd-im...@googlegroups.com
The very minor possible speed gain (which is dwarfed by any network
activity) is not worth the extra complication of expanding the API and
the burden on implementers to match. This has not come up as an issue
in real world scenarios.

The bigger problem is what Eric alludes to -- not having a compatible
API to kick off dependency resolution. I would rather see work put
into solving the larger problems first.

James

Taka Kojima

unread,
Mar 2, 2012, 5:11:00 PM3/2/12
to amd-im...@googlegroups.com
Standardizing this and implementing this actually solves Eric's bigger issue as well.

By requiring any file that defines more than one module to explicitly state at the top of the file what modules it defines, you are able to implement:

define("main", ["a","b","c"], function(a,b,c) {

});

Without worrying about the problem that comes up by deferring define() calls. This allows you to use define() out of the context of a "loaded js module/file".

I'll post a response in that other thread with a couple other ideas.

Taka

James Burke

unread,
Mar 2, 2012, 5:25:49 PM3/2/12
to amd-im...@googlegroups.com
On Fri, Mar 2, 2012 at 2:11 PM, Taka Kojima <ta...@gigafied.com> wrote:
> Standardizing this and implementing this actually solves Eric's bigger issue
> as well.
>
> By requiring any file that defines more than one module to explicitly state
> at the top of the file what modules it defines, you are able to implement:

That only helps inform the loader what might show up in the file, it
does not tell the loader when to start executing factory functions.
There are some folks that do not want to execute the factory functions
until they are actually required by something, so they can seed a few
modules in a built file, but not take the overhead of running them
until they are needed. The execution chain needs to start somewhere,
usually with a global require()-like kickoff, which is likely at the
end of the file.

James

Taka Kojima

unread,
Mar 2, 2012, 6:21:20 PM3/2/12
to amd-im...@googlegroups.com
In Needs, all dependencies are loaded recursively, and all factory functions are executed at the time of the define call, this may not be how RequireJS does it. In RequireJS do you add all defines() to an object, then only invoke those define calls when/if they are needed?

So, now your response makes sense. In Needs, doing this:

define("main", ["a","b","c"], function(a,b,c) {

});

would work to replace the global-level require() entry point, however in RequireJS this wouldn't work because while "main" is defined, neither it's factory function or dependencies have been loaded.

I guess we have two rather different approaches then. I see no mention in the spec of how to handle the loading/execution of module dependencies/factory functions.

Is the method used in RequireJS any sort of standard or commonly-implemented-this-way type of deal? Is it something that would or could possibly be standardized in the AMD spec?

I see where not executing the factory function in the actual define() might make sense, however at least in my use cases, my factory functions don't really do much that would entail any sort of undesirable overhead. Anything expensive happens in methods and objects returned from the factory function.

Taka

Rawld

unread,
Mar 2, 2012, 6:37:51 PM3/2/12
to amd-im...@googlegroups.com
On 03/02/2012 11:31 AM, James Burke wrote:
> As Eric mentioned, we've talked a bit on this before. I favor just
> using a global require, but the folks that prefer not to use that,
> IIRC, John Hann and Rawld, I do not think have proposed something
> else.

I don't remember objecting to that (maybe I did...just don't remember).

Anyhow, I don't object to that now: I also favor global require.

> Using anything on define() seems like the incorrect place, as I
> mentioned in that thread that Eric mentioned.

I agree that overloading define() is not the correct approach: to demand
several modules is not equivalent to defining a module.

fwiw, James' early API had one global function, namely require. He
augmented the API to differentiate between define and require as was
requested by many. I don't think trying stuff everything into define()
(now that we have it) makes sense given history.
> Some requirejs specific notes below�

Eric Bréchemier

unread,
Mar 3, 2012, 3:41:42 AM3/3/12
to amd-im...@googlegroups.com
>> Using anything on define() seems like the incorrect place, as I
>> mentioned in that thread that Eric mentioned.
>
> I agree that overloading define() is not the correct approach: to demand
> several modules is not equivalent to defining a module.
>
> fwiw, James' early API had one global function, namely require. He augmented
> the API to differentiate between define and require as was requested by
> many. I don't think trying stuff everything into define() (now that we have
> it) makes sense given history.

You have a good point. One thing though: AMD promotes modular
development for JavaScript, each module being associated with an id in
a scope separated from the global namespace. But for two different
functions, AMD would take ownership of two different names in the
global namespace?

I feel like we should follow good practice here, and group both
require() and define() in a single global namespace, for example amd:
* amd.define()
* amd.require()
* ...

This would definitely avoid some confusion with separate
specifications for global require().

Cheers,

Eric

James Burke

unread,
Mar 4, 2012, 8:21:53 PM3/4/12
to amd-im...@googlegroups.com
On Fri, Mar 2, 2012 at 3:21 PM, Taka Kojima <ta...@gigafied.com> wrote:
> Is the method used in RequireJS any sort of standard or
> commonly-implemented-this-way type of deal? Is it something that would or
> could possibly be standardized in the AMD spec?

I think that is because we are still discovering the right execution
model, or that both should be allowed. RequireJS actually does a
hybrid approach: it collects the define calls, but waits for a
require() call to trigger the factory functions, and at that point
**all** define factory functions are called.

However, some users of almond, and some folks in requirejs land point
out that the execution of all define factories (in the order they are
registered) can be a different than the order used in dev, and some
things that do stuff like CSS work can be expensive to do all at once.
So I'm looking at changing it to only trace direct dependencies of a
require instead of all define() calls, for requirejs 1.1.

It would be curious to hear other implementers and their take on it.
If we agree on a model, then we can at least write it up as a standard
approach. It can be in a separate API doc, not the main AMD one if
that made more sense.

James

Richard Backhouse

unread,
Mar 4, 2012, 9:05:57 PM3/4/12
to amd-im...@googlegroups.com
I think it would be a bad idea for the spec to mandate this sort of
thing. Personally my AMD loaders call the factories on-demand, not when
the define method is called.

James Burke

unread,
Mar 5, 2012, 12:14:51 AM3/5/12
to amd-im...@googlegroups.com
On Sat, Mar 3, 2012 at 12:41 AM, Eric Bréchemier
<eric.br...@gmail.com> wrote:
> You have a good point. One thing though: AMD promotes modular
> development for JavaScript, each module being associated with an id in
> a scope separated from the global namespace. But for two different
> functions, AMD would take ownership of two different names in the
> global namespace?
>
> I feel like we should follow good practice here, and group both
> require() and define() in a single global namespace, for example amd:
> * amd.define()
> * amd.require()

I would not be opposed to that as an option, but I do like at least
for define() to be available globally. If there needed to be some
disambiguation with another global define/require then allowing the
use of amd.define and amd.require seems fine.

I'm hoping there is not more new things to add for a top level API.
Since require() is used inside of define(), I think it is a concept
that carries over well to global usage, so I think we could get by
without mandating the use of amd.require and amd.define at the top
level. define() is already in wide usage as a global. But if this is a
big enough blocker for other implementers, who feel that
amd.require/amd.define should be available (at the very least,
amd.require() for the top level), I am open to changing requirejs to
allow for it.

But if it was just me, I would see how far I could go with just
keeping define and possibly using require as a global, instead of
creating a new 'amd' global.

James

James Burke

unread,
Mar 5, 2012, 12:17:35 AM3/5/12
to amd-im...@googlegroups.com
On Sun, Mar 4, 2012 at 6:05 PM, Richard Backhouse
<richarda...@gmail.com> wrote:
> I think it would be a bad idea for the spec to mandate this sort of thing.
> Personally my AMD loaders call the factories on-demand, not when the define
> method is called.

FWIW, if we were to try to standardize something, I could see
standardizing the behavior you are using -- only execute factories on
a direct require/reference vs. when define() is called or executing
all defines at a certain time regardless of whether it was directly
asked for by a top level loader call.

I'm fine though waiting a bit on that, and seeing how it shakes out for people.

James

Taka Kojima

unread,
Mar 5, 2012, 12:38:09 AM3/5/12
to amd-im...@googlegroups.com
FWIW, if we were to try to standardize something, I could see
standardizing the behavior you are using -- only execute factories on
a direct require/reference vs. when define() is called or executing
all defines at a certain time regardless of whether it was directly
asked for by a top level loader call.
 
The more I think about it, the more it makes sense to do it this way, as it would provide the most consistency between the non-built version of your app, and the built version.

When modules are defined in individual files (i.e. during the dev process), the factory functions only get invoked when they are needed. Even if this technically happens during define(), modules aren't loaded unless they are required() somewhere in your application. Thus it behaves much like only invoking the factory function upon said module being required.

When in production and using a built file, you may provide definitions for a lot of modules up front. Having the factory methods execute only when they are needed makes the most sense, as this is how you would expect it to behave locally during development, so it should behave the same way when built.

For a lot of cases it won't matter, but having that consistency there makes sense and I think it is something that should be standardized.

// module/a
define(function(){
    window.something = "a";
    
    return function () {
        console.log(window.something);
    }
});

// module/b
define(function(){
    window.something = "b";
    
    return function () {
        console.log(window.something);
    }
});

During dev, if I do:

require(["module/a"], function (a) {
    a();
});

console.log() will print "a"

However, if I built module/a with module/b, during production (if I was executing the factory functions upon define, vs when they are required), console.log() will print "b".

Obviously, the above is a very good example of HOW NOT to write code, but it illustrates the point. Anything that promotes consistency between an AMD-based project between dev and production is something that should be standardized.

Bad code or not, I shouldn't get entirely different behavior if I'm running my site with anonymous modules pre-build, or concat & minified production build.

There's also the matter of pre-fetching dependencies, which I think is something that doesn't have to be standardized. If some loader wants to prefetch dependencies, found in a built file, then I think that's fine. If other loaders prefer to only fetch the needed modules when actually required, I think that is also fine.

Taka

Domenic Denicola

unread,
Mar 5, 2012, 4:48:52 AM3/5/12
to amd-im...@googlegroups.com
> FWIW, if we were to try to standardize something, I could see standardizing the behavior you are using -- only execute factories on direct require/reference vs. when define() is called or executing all defines at a certain time regardless of whether it was directly asked for by a top level loader call.

Wasn't this one of the main departures of AMD from CommonJS in the first place? Or between AMD and the present-day CommonJS Modules/2.0 or UncommonJS Modules specs?

http://tagneto.blogspot.com/2010/12/standards-and-proposals-for-javascript.html "AMD and Wrappings Differences"

What's changed?

James Burke

unread,
Mar 5, 2012, 1:41:57 PM3/5/12
to amd-im...@googlegroups.com
On Mon, Mar 5, 2012 at 1:48 AM, Domenic Denicola
<dom...@domenicdenicola.com> wrote:
> Wasn't this one of the main departures of AMD from CommonJS in the first place? Or between AMD and the present-day CommonJS Modules/2.0 or UncommonJS Modules specs?
>
> http://tagneto.blogspot.com/2010/12/standards-and-proposals-for-javascript.html "AMD and Wrappings Differences"
>
> What's changed?

This is slightly different than that. AMD should still execute all of
the direct dependencies for a given module.

What I want to change in requirejs: it currently runs *every* define
call in a built file, regardless on whether it was referenced as a
direct dependency. A direct dependency is one listed in the dependency
array or as a string literal require('') call (for simplified CJS
wrapping).

So for this module:

//main.js
define(['require', 'a', 'b'], function(require, a, b) {

return function (cb) {
require(['c'], cb);
});
});

If the built file contained the modules in this order: 'c', 'b', 'a',
'main', requirejs will execute c and b before a and main (assuming c
and b did not have dependencies) once a require()/requirejs() call
runs at the end of the file.

What I want to change: c's factory is not executed until it is
directly referenced, and that only factories that are explicitly
referenced as dependencies are executed, and in the order they are
referenced.

However, the 'a' and 'b' factories are still executed before executing
main's factory (the departure point for AMD and CJS). So, for the
initial file execution, the factory execution order would be:

* a
* b
* main

then at some time later, when main's exported function is called, c's
factory is run. If c also directly depended on 'd' (and a, b, main did
not), then d's factory function would then be executed before c's
factory.

James

Rawld

unread,
Mar 5, 2012, 2:06:11 PM3/5/12
to amd-im...@googlegroups.com
On 03/04/2012 09:14 PM, James Burke wrote:
> On Sat, Mar 3, 2012 at 12:41 AM, Eric Br�chemier

> <eric.br...@gmail.com> wrote:
>> You have a good point. One thing though: AMD promotes modular
>> development for JavaScript, each module being associated with an id in
>> a scope separated from the global namespace. But for two different
>> functions, AMD would take ownership of two different names in the
>> global namespace?
>>
>> I feel like we should follow good practice here, and group both
>> require() and define() in a single global namespace, for example amd:
>> * amd.define()
>> * amd.require()
> I would not be opposed to that as an option, but I do like at least
> for define() to be available globally. If there needed to be some
> disambiguation with another global define/require then allowing the
> use of amd.define and amd.require seems fine.
I agree, but I can't come up with a rational argument that it should be
this way other than taste and history. James--do you have some specific
reasons for this opinion?

> I'm hoping there is not more new things to add for a top level API.
> Since require() is used inside of define(), I think it is a concept
> that carries over well to global usage, so I think we could get by
> without mandating the use of amd.require and amd.define at the top
> level. define() is already in wide usage as a global. But if this is a
> big enough blocker for other implementers, who feel that
> amd.require/amd.define should be available (at the very least,
> amd.require() for the top level), I am open to changing requirejs to
> allow for it.
>
> But if it was just me, I would see how far I could go with just
> keeping define and possibly using require as a global, instead of
> creating a new 'amd' global.
So if we have define and amd, we still have two global vars. I can see
how taking ownership of "amd" in the global namespace should be less
controversial than taking ownership of "require". So that seems reasonable.

Just for the sake of argument, assume we did this. The pseudo-module
"require" could also be renamed "amd". This means passing an object
instead of a function which allows for providing a prototypical
inheritance chain which is cheaper than copying properties to a closure.

Still, these seem to be fairly large changes at this point in AMD's life
cycle. I'm not at all convinced any of them are worth the chaos they
would cause.

--Rawld

Rawld

unread,
Mar 5, 2012, 2:26:15 PM3/5/12
to amd-im...@googlegroups.com
On 03/04/2012 05:21 PM, James Burke wrote:
On Fri, Mar 2, 2012 at 3:21 PM, Taka Kojima <ta...@gigafied.com> wrote:
Is the method used in RequireJS any sort of standard or
commonly-implemented-this-way type of deal? Is it something that would or
could possibly be standardized in the AMD spec?
I think that is because we are still discovering the right execution
model, or that both should be allowed. RequireJS actually does a
hybrid approach: it collects the define calls, but waits for a
require() call to trigger the factory functions, and at that point
**all** define factory functions are called.

I've implemented bdLoad/dojo so that module eval order is well-defined whether or not you are loading a built or unbuilt code stack.

Recall from Taka's earlier message in this thread, this code:


//someFile.js

define("d", ["a", "b","c"], {something: true});
define("a", {something: true});
define("b", {
something: true});
define("c", {
something: true});

Presumably, the intention is a resource that contains modules a-d. However, I believe this design is flawed because it makes the assumption that any "source" resource contains exactly one define application *and nothing else*. Usually, this is the case. But there is no reason is it a requirement, and a module may contain other code before and/or after the define application.

The bdLoad/bdBuild/dojo build systems/loaders solve the problem by maintaining a client-side cache of modules that may be added to and then consumed as required. Assuming the example above had the purpose of defining "d" and aggregating "a", "b", and "c", the dojo builder output would look like this:

require({
  cache:{
    "a":function(){
       // all of the code that was in the resource that defined module "a"
    },
    "b":function(){
       // all of the code that was in the resource that defined module "b"
    },
    "c":function(){
       // all of the code that was in the resource that defined module "c"
    }
}});
define("d", ["a", "b","c"], {something: true});

When the loader processes the require call, it notices it is a configuration application that provides a cache value, and adds the modules a, b, and c to the module cache...it does not execute those functions...e.g. it just adds the property "a" with the function value to the cache (there is some special stuff that goes on to deal with mapping...but we can talk about that later). Multiple cache configs can be consumed.

Then the define application is processed as usual.

Finally, when some require chain actually requires any of "a", "b", of "c", the loader first looks in the cache before downloading...if found, *then* it evaluates the function...thereby causing unbuilt and built to work *exactly* the same.

--Rawld





Taka Kojima

unread,
Mar 5, 2012, 2:46:28 PM3/5/12
to amd-im...@googlegroups.com
require({
  cache:{
    "a":function(){
       // all of the code that was in the resource that defined module "a"
    },
    "b":function(){
       // all of the code that was in the resource that defined module "b"
    },
    "c":function(){
       // all of the code that was in the resource that defined module "c"
    }
}});
define("d", ["a", "b","c"], {something: true}); 


This makes sense Rawld, it's along the same lines of how I am refactoring Needs to work.

However, in my implementation the file still looks like this:

define("d", ["a", "b","c"], {something: true});
define("a", {something: true});
define("b", {
something: true});
define("c", {
something: true});

Upon define(), a module checks to see if it's id exists in a _requiredModules array. If the module is in _requiredModules, then its factory function is invoked, otherwise, it goes to the cache.

Whenever you call require(), the modules you require get pushed to _requiredModules. My implementation of define() uses require() to get dependencies, so this works well recursively.

Taka

James Burke

unread,
Mar 5, 2012, 8:15:25 PM3/5/12
to amd-im...@googlegroups.com
On Mon, Mar 5, 2012 at 11:06 AM, Rawld <rg...@altoviso.com> wrote:
> On 03/04/2012 09:14 PM, James Burke wrote:
>> I would not be opposed to that as an option, but I do like at least
>> for define() to be available globally. If there needed to be some
>> disambiguation with another global define/require then allowing the
>> use of amd.define and amd.require seems fine.
>
> I agree, but I can't come up with a rational argument that it should be this
> way other than taste and history. James--do you have some specific reasons
> for this opinion?

Yeah, I think it is just history. define() is already in the wild, it
is short too. Boilerplate is a real big turn-off, so the less the
better. Also, I think the hope was to be able to have a new require
API in CommonJS that would support the require needs in the browser.

Also, AMD did not get a real identity until later. I actually do not
like the name "AMD", too confusing with the chipset maker, I keep
reading the MD part as "mass destruction". :) But naming is hard, and
when talking about the initial API draft, I just used the name Kris
Zyp gave it, because naming is hard, and it was an API draft. But the
name seems to have stuck. The name of this list is not helping either.
:)

>> I'm hoping there is not more new things to add for a top level API.
>> Since require() is used inside of define(), I think it is a concept
>> that carries over well to global usage, so I think we could get by
>> without mandating the use of amd.require and amd.define at the top
>> level. define() is already in wide usage as a global. But if this is a
>> big enough blocker for other implementers, who feel that
>> amd.require/amd.define should be available (at the very least,
>> amd.require() for the top level), I am open to changing requirejs to
>> allow for it.
>>
>> But if it was just me, I would see how far I could go with just
>> keeping define and possibly using require as a global, instead of
>> creating a new 'amd' global.
>
> So if we have define and amd, we still have two global vars. I can see how
> taking ownership of "amd" in the global namespace should be less
> controversial than taking ownership of "require". So that seems reasonable.
>
> Just for the sake of argument, assume we did this. The pseudo-module
> "require" could also be renamed "amd". This means passing an object instead
> of a function which allows for providing a prototypical inheritance chain
> which is cheaper than copying properties to a closure.

That seems awkward to me. Maybe my eyes have just adjusted to using
"require" as the dependency name. I have thought of a use case that
may warrant a special dependency name "define", to allow defining
modules local to just that module, but it is really just a thought. I
prefer the shorter, functional API names, even though as you say the
prototype options are nice. Although, I can see problems if the
implementation does not allow var var req = amd.require; and it means
builders have more variations like that to parse out for static
analysis. Or it means mandating only using 'amd.require' in the files.
Yuck. The fact that require is used in define to me is enough to
namespace the require. "require" is already a special dependency name
anyway/already used in code, I say that boat has sailed.

So, I do not like the idea of a special "amd" dependency name, like
"require", "exports" and "module" are now.

> Still, these seem to be fairly large changes at this point in AMD's life
> cycle. I'm not at all convinced any of them are worth the chaos they would
> cause.

For me the only reason to consider an amd.require() is to get a
distinction from a Node/CommonJS "require" that might also be in scope
for some reason, and to overcome the objections that folks like John
Hann have about just using "require" in the global space.

Previously I had not really considered using "amd" for the object name
though, since I was not a fan of the actual name. And I think the hope
was that its APIs would just be a standard module loading API. No need
to group it under a namespace, it just "is".

If it gets us to a "common global entry point" API, then I'm open to
considering it further, but I do still favor just using require(). If
we go with "amd.require" at this point I would only want to spec out
"amd.require" and not an "amd.define" or anything else, and it should
only be a global, not a special dependency name.

But I would first want to get an idea on if "require" is just not
usable. I would like to see "make a require function available if
there is not already one there, and make sure your loader has a
loader-specific global API in case the developer really wants to call
your library in case of a require conflict. That global require is
only expected to support the API as specified for the local 'require'
spec. A loader may add other things, but they would be non-standard,
and not dependable for use as a top-level require call for loader
interop."

James

James Burke

unread,
Mar 5, 2012, 8:20:15 PM3/5/12
to amd-im...@googlegroups.com
On Mon, Mar 5, 2012 at 11:26 AM, Rawld <rg...@altoviso.com> wrote:

This is the approach I'm looking to convert to, except that all
define() calls are effectively like the require.cache calls, and only
a global require()/requirejs() call triggers the factory executions,
and only for modules that are directly referenced for that call's
dependency graph.

James

Rawld

unread,
Mar 5, 2012, 11:14:17 PM3/5/12
to amd-im...@googlegroups.com
On 03/05/2012 05:15 PM, James Burke wrote:
>
> Also, AMD did not get a real identity until later. I actually do not
> like the name "AMD", too confusing with the chipset maker, I keep
> reading the MD part as "mass destruction". :) But naming is hard, and
> when talking about the initial API draft, I just used the name Kris
> Zyp gave it, because naming is hard, and it was an API draft. But the
> name seems to have stuck. The name of this list is not helping either.
> :)
Right...iirc, when Kris originally wrote the spec he named it
modules/asynchronous definitions...and I referred to it as MAD a few
times in IRC :)

I was just kinda thinking out loud if we would've gone in a completely
different direction. But that's water under the bridge and I'm
definitely not proposing anything.

On the central point--should we define global require?--I'm with James.
I would vote yes on that. It seems like we could impl require to work as
an augmented CommonJS/node.js require. As always, I would favor a
has-bracketed impl that did not cost browser clients extra code. This
idea is on my list to look into.

> But I would first want to get an idea on if "require" is just not
> usable. I would like to see "make a require function available if
> there is not already one there, and make sure your loader has a
> loader-specific global API in case the developer really wants to call
> your library in case of a require conflict. That global require is
> only expected to support the API as specified for the local 'require'
> spec. A loader may add other things, but they would be non-standard,
> and not dependable for use as a top-level require call for loader
> interop."
>

Agree.

--Rawld


Taka Kojima

unread,
Mar 6, 2012, 1:38:26 AM3/6/12
to amd-im...@googlegroups.com
I'm all for a global require, it's actually fairly easy to augment the global require too, something like:

if (require) {

_globalReq = require;

require = function () {
if (arguments.length > 1) {
return req.apply(this, arguments);
}
else {
return _globalReq.apply(this, arguments);
}
}
}

else {
require = req;
}

Where `req` is a reference to the AMD version of the global require, I think if implemented this way, people would get used to it fairly easily.

I mean, when writing JS on the server-side (or client-side for that matter) and you see code like this:

someFunc("someArg", function () {

});

Anybody that has been writing JavaScript for more than a day could tell you that someFunc is executing something async and wants the function it provided as the second argument to be invoked after someFunc does its thing.

Taka

Taka Kojima

unread,
Mar 6, 2012, 1:39:48 AM3/6/12
to amd-im...@googlegroups.com
Disregard, just remembered this little tidbit from the Node.js docs:

"require isn't actually a global but rather local to each module."
Reply all
Reply to author
Forward
0 new messages