Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
Ideas for standardizing built AMD files
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  25 messages - Collapse all  -  Translate all to Translated (View all originals)
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Taka Kojima  
View profile  
 More options Mar 1 2012, 4:02 pm
From: Taka Kojima <t...@gigafied.com>
Date: Thu, 1 Mar 2012 13:02:19 -0800
Local: Thurs, Mar 1 2012 4:02 pm
Subject: Ideas for standardizing built AMD files

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.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Eric Bréchemier  
View profile  
 More options Mar 2 2012, 9:20 am
From: Eric Bréchemier <eric.brechem...@gmail.com>
Date: Fri, 2 Mar 2012 15:20:41 +0100
Local: Fri, Mar 2 2012 9:20 am
Subject: Re: [amd-implement] Ideas for standardizing built AMD files
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/2f...

> 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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
James Burke  
View profile  
 More options Mar 2 2012, 2:31 pm
From: James Burke <jrbu...@gmail.com>
Date: Fri, 2 Mar 2012 11:31:12 -0800
Local: Fri, Mar 2 2012 2:31 pm
Subject: Re: [amd-implement] Ideas for standardizing built AMD files
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 <t...@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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Taka Kojima  
View profile  
 More options Mar 2 2012, 2:55 pm
From: Taka Kojima <t...@gigafied.com>
Date: Fri, 2 Mar 2012 11:55:15 -0800
Local: Fri, Mar 2 2012 2:55 pm
Subject: Re: [amd-implement] Ideas for standardizing built AMD files

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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
James Burke  
View profile  
 More options Mar 2 2012, 4:30 pm
From: James Burke <jrbu...@gmail.com>
Date: Fri, 2 Mar 2012 13:30:24 -0800
Local: Fri, Mar 2 2012 4:30 pm
Subject: Re: [amd-implement] Ideas for standardizing built AMD files
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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Taka Kojima  
View profile  
 More options Mar 2 2012, 5:11 pm
From: Taka Kojima <t...@gigafied.com>
Date: Fri, 2 Mar 2012 14:11:00 -0800
Subject: Re: [amd-implement] Ideas for standardizing built AMD files

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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
James Burke  
View profile  
 More options Mar 2 2012, 5:25 pm
From: James Burke <jrbu...@gmail.com>
Date: Fri, 2 Mar 2012 14:25:49 -0800
Local: Fri, Mar 2 2012 5:25 pm
Subject: Re: [amd-implement] Ideas for standardizing built AMD files

On Fri, Mar 2, 2012 at 2:11 PM, Taka Kojima <t...@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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Taka Kojima  
View profile  
 More options Mar 2 2012, 6:21 pm
From: Taka Kojima <t...@gigafied.com>
Date: Fri, 2 Mar 2012 15:21:20 -0800
Local: Fri, Mar 2 2012 6:21 pm
Subject: Re: [amd-implement] Ideas for standardizing built AMD files

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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Rawld  
View profile  
 More options Mar 2 2012, 6:37 pm
From: Rawld <rg...@altoviso.com>
Date: Fri, 02 Mar 2012 15:37:51 -0800
Local: Fri, Mar 2 2012 6:37 pm
Subject: Re: [amd-implement] Ideas for standardizing built AMD files
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.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Eric Bréchemier  
View profile  
 More options Mar 3 2012, 3:41 am
From: Eric Bréchemier <eric.brechem...@gmail.com>
Date: Sat, 3 Mar 2012 09:41:42 +0100
Local: Sat, Mar 3 2012 3:41 am
Subject: Re: [amd-implement] Ideas for standardizing built AMD files

>> 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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
James Burke  
View profile  
 More options Mar 4 2012, 8:21 pm
From: James Burke <jrbu...@gmail.com>
Date: Sun, 4 Mar 2012 17:21:53 -0800
Local: Sun, Mar 4 2012 8:21 pm
Subject: Re: [amd-implement] Ideas for standardizing built AMD files

On Fri, Mar 2, 2012 at 3:21 PM, Taka Kojima <t...@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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Richard Backhouse  
View profile  
 More options Mar 4 2012, 9:05 pm
From: Richard Backhouse <richardabackho...@gmail.com>
Date: Sun, 04 Mar 2012 21:05:57 -0500
Local: Sun, Mar 4 2012 9:05 pm
Subject: Re: [amd-implement] Ideas for standardizing built AMD files
On 3/4/12 8:21 PM, James Burke 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.

 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
James Burke  
View profile  
 More options Mar 5 2012, 12:14 am
From: James Burke <jrbu...@gmail.com>
Date: Sun, 4 Mar 2012 21:14:51 -0800
Local: Mon, Mar 5 2012 12:14 am
Subject: Re: [amd-implement] Ideas for standardizing built AMD files
On Sat, Mar 3, 2012 at 12:41 AM, Eric Bréchemier

<eric.brechem...@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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
James Burke  
View profile  
 More options Mar 5 2012, 12:17 am
From: James Burke <jrbu...@gmail.com>
Date: Sun, 4 Mar 2012 21:17:35 -0800
Local: Mon, Mar 5 2012 12:17 am
Subject: Re: [amd-implement] Ideas for standardizing built AMD files
On Sun, Mar 4, 2012 at 6:05 PM, Richard Backhouse

<richardabackho...@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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Taka Kojima  
View profile  
 More options Mar 5 2012, 12:38 am
From: Taka Kojima <t...@gigafied.com>
Date: Sun, 4 Mar 2012 21:38:09 -0800
Local: Mon, Mar 5 2012 12:38 am
Subject: Re: [amd-implement] Ideas for standardizing built AMD files

> 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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Domenic Denicola  
View profile  
 More options Mar 5 2012, 4:48 am
From: Domenic Denicola <dome...@domenicdenicola.com>
Date: Mon, 5 Mar 2012 09:48:52 +0000
Local: Mon, Mar 5 2012 4:48 am
Subject: RE: [amd-implement] Ideas for standardizing built AMD files

> 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-javas... "AMD and Wrappings Differences"

What's changed?


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
James Burke  
View profile  
 More options Mar 5 2012, 1:41 pm
From: James Burke <jrbu...@gmail.com>
Date: Mon, 5 Mar 2012 10:41:57 -0800
Local: Mon, Mar 5 2012 1:41 pm
Subject: Re: [amd-implement] Ideas for standardizing built AMD files
On Mon, Mar 5, 2012 at 1:48 AM, Domenic Denicola

<dome...@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-javas... "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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Rawld  
View profile  
 More options Mar 5 2012, 2:06 pm
From: Rawld <rg...@altoviso.com>
Date: Mon, 05 Mar 2012 11:06:11 -0800
Local: Mon, Mar 5 2012 2:06 pm
Subject: Re: [amd-implement] Ideas for standardizing built AMD files
On 03/04/2012 09:14 PM, James Burke wrote:

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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Rawld  
View profile  
 More options Mar 5 2012, 2:26 pm
From: Rawld <rg...@altoviso.com>
Date: Mon, 05 Mar 2012 11:26:15 -0800
Local: Mon, Mar 5 2012 2:26 pm
Subject: Re: [amd-implement] Ideas for standardizing built AMD files

On 03/04/2012 05:21 PM, James Burke wrote:

> On Fri, Mar 2, 2012 at 3:21 PM, Taka Kojima<t...@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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Taka Kojima  
View profile  
 More options Mar 5 2012, 2:46 pm
From: Taka Kojima <t...@gigafied.com>
Date: Mon, 5 Mar 2012 11:46:28 -0800
Local: Mon, Mar 5 2012 2:46 pm
Subject: Re: [amd-implement] Ideas for standardizing built AMD files

> 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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
James Burke  
View profile  
 More options Mar 5 2012, 8:15 pm
From: James Burke <jrbu...@gmail.com>
Date: Mon, 5 Mar 2012 17:15:25 -0800
Local: Mon, Mar 5 2012 8:15 pm
Subject: Re: [amd-implement] Ideas for standardizing built AMD files

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.
:)

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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
James Burke  
View profile  
 More options Mar 5 2012, 8:20 pm
From: James Burke <jrbu...@gmail.com>
Date: Mon, 5 Mar 2012 17:20:15 -0800
Local: Mon, Mar 5 2012 8:20 pm
Subject: Re: [amd-implement] Ideas for standardizing built AMD files

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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Rawld  
View profile  
 More options Mar 5 2012, 11:14 pm
From: Rawld <rg...@altoviso.com>
Date: Mon, 05 Mar 2012 20:14:17 -0800
Local: Mon, Mar 5 2012 11:14 pm
Subject: Re: [amd-implement] Ideas for standardizing built AMD files
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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Taka Kojima  
View profile  
 More options Mar 6 2012, 1:38 am
From: Taka Kojima <t...@gigafied.com>
Date: Mon, 5 Mar 2012 22:38:26 -0800
Local: Tues, Mar 6 2012 1:38 am
Subject: Re: [amd-implement] Ideas for standardizing built AMD files

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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Taka Kojima  
View profile  
 More options Mar 6 2012, 1:39 am
From: Taka Kojima <t...@gigafied.com>
Date: Mon, 5 Mar 2012 22:39:48 -0800
Local: Tues, Mar 6 2012 1:39 am
Subject: Re: [amd-implement] Ideas for standardizing built AMD files

Disregard, just remembered this little tidbit from the Node.js docs:

"require isn't actually a global but rather local to each module."


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
End of messages
« Back to Discussions « Newer topic     Older topic »