Common configuration draft

276 views
Skip to first unread message

James Burke

unread,
Jun 30, 2012, 12:05:00 PM6/30/12
to amd-im...@googlegroups.com
There is a draft of the common configuration values now on the AMD
wiki. It is marked as DRAFT:

https://github.com/amdjs/amdjs-api/wiki/Common-Config

Please give a holler if you see problems with it. It is based on this
earlier draft:

https://gist.github.com/1630091

that was already discussed on the list. The changes from that draft:

* The map config is now its own config, not nested under paths or
packages, and it allows for a * config, and use of any module prefix.
* paths allows support for array values instead of strings, if the
loader supports fallback/failover loading.

We can take the DRAFT off if this seems generally acceptable and/or
there are more loaders that confirm they implement them. Right now
requirejs supports all of them.

Note that they are optional. A loader does not have to provide them or
can only choose to provide a subset. The main point is for us to
standardize on some for basic interop, if the loaders provide similar
functionality.

One that I did not specify, but have found very welcome in the
requirejs community is "shim":

http://requirejs.org/docs/api.html#config-shim

but given that it is for helping legacy, non-AMD modules to
participate in AMD loading, I did not think it was appropriate to put
in the list, unless I hear from other AMD loader implementers that
they would want to support it too.

James

Ben Hockey

unread,
Jul 16, 2012, 3:49:25 PM7/16/12
to amd-im...@googlegroups.com
i'm confused...

* The map config is now its own config, not nested under paths or
packages...

in https://github.com/amdjs/amdjs-api/wiki/Common-Config it has the following under packages
map: Object. Optional. See [details under the map section.

but it seems you're saying this is not how it works now.

it's also still unclear if the spec supports the use case i asked about at https://groups.google.com/d/msg/amd-implement/_vt4K62no4M/uxbXd4afWXUJ - the ability to do wholesale mapping per package is critical and is the primary use case supported by dojo's pacakgeMap.  i would hate to have to list out every module in every package in order to get them properly mapped.  i get the impression from the spec that the mapping is only supposed to happen per module id.  for example with the following map

map: {
  pkgA: {
    // a map of module id prefixes to be remapped for any modules mapped into the pkgA prefix/package
    foo: "foo1.2"
  }
}

if the pkgA module depends on "foo", i expect it will get "foo1.2".  if pkgA/moduleX depends on "foo", what should i see?  i *think* that the spec allows for it to be "foo1.2" but i'm uncertain because it doesn't say so explicitly and every example i've seen (including requirejs tests) explicitly map the specific module being used but don't demonstrate what should happen for modules that share the same prefix.  an example, if https://github.com/jrburke/requirejs/blob/2.0.4/tests/mapConfig/mapConfig-tests.js required "a/sub" and that module had a dependency on "c", will it get "c" or "c1" or something else?  i hope it gets "c1".

if we agree with how this should work then i'd like to see something in the spec that more clearly says that all modules that have a prefix that matches a prefix in the map, the dependencies will be remapped according to the map config.

thanks,

ben...

Rawld Gill

unread,
Jul 16, 2012, 3:55:15 PM7/16/12
to amd-im...@googlegroups.com

> -----Original Message-----
> From: amd-im...@googlegroups.com [mailto:amd-
> impl...@googlegroups.com] On Behalf Of Ben Hockey
> Sent: Monday, July 16, 2012 12:49 PM
> To: amd-im...@googlegroups.com
> Subject: [amd-implement] Re: Common configuration draft
>
> i'm confused...
>
>
> * The map config is now its own config, not nested under paths or
> packages...

It is still nested under packages...look just above in the spec. And I think that is where the equivalent of dojo's packageMap takes place and answers the questions below.

Let me know if I'm not understanding your observation.

>
>
> in https://github.com/amdjs/amdjs-api/wiki/Common-Config it has the
> following under packages
>
> map: Object. Optional. See [details under the map
> <https://github.com/amdjs/amdjs-api/wiki/Common-Config#wiki-map>

Rawld Gill

unread,
Jul 16, 2012, 4:06:50 PM7/16/12
to amd-im...@googlegroups.com
I pushed send too fast...

> -----Original Message-----
> From: amd-im...@googlegroups.com [mailto:amd-
> impl...@googlegroups.com] On Behalf Of Ben Hockey
> Sent: Monday, July 16, 2012 12:49 PM


> for example with the following map
>
> map: {
> pkgA: {
> // a map of module id prefixes to be remapped for any modules mapped into
> the pkgA prefix/package
> foo: "foo1.2"
> }
> }
>
> if the pkgA module depends on "foo", i expect it will get "foo1.2". if
> pkgA/moduleX depends on "foo", what should i see? i *think* that the spec
> allows for it to be "foo1.2" but i'm uncertain because it doesn't say so explicitly
> and every example i've seen (including requirejs tests) explicitly map the specific
> module being used but don't demonstrate what should happen for modules that
> share the same prefix. an example, if
> https://github.com/jrburke/requirejs/blob/2.0.4/tests/mapConfig/mapConfig-
> tests.js required "a/sub" and that module had a dependency on "c", will it get
> "c" or "c1" or something else? i hope it gets "c1".

I understand the above map to say the module "pkgA"--and only that single module--will map the dependency "foo" in pkgA's deps vector to "foo1.2".

If pkgA is in fact a package and I want and foo/* dependency within any pkgA module to map to foo1.2, then I'd write the config as follows:

packages:{[
name:"pkgA",
location://etc.
map:{
"*":{
foo:"foo1.2"
}
}
},{
name:"foo1.2",
//etc.
}]

>
> if we agree with how this should work then i'd like to see something in the spec
> that more clearly says that all modules that have a prefix that matches a prefix in
> the map, the dependencies will be remapped according to the map config.

So, as I understand the spec, map is defined as follows:

map:(module-id or "*") --> (map:(prefix) --> replacement)

--Rawld

Ben Hockey

unread,
Jul 16, 2012, 5:22:27 PM7/16/12
to amd-im...@googlegroups.com
It is still nested under packages...look just above in the spec. And I think that is where the equivalent of dojo's packageMap takes place and answers the questions below. 

we need james to clarify his intentions with the changes he made when translating the spec from the gist to the wiki.  

based on the comments in james' initial post on this thread, my concern is that the piece about map in the package section of the wiki is a remnant that he may have intended to remove.  it's hard to say for certain because i'm trying to piece this together based on comments here, the spec in the wiki, the spec in the gist and all our previous discussion based on the content in the gist.

the way that map is described in the wiki, it doesn't really look like there is an intention for it to be used under the config for a package - maybe i'm wrong.

the other part that needs clarification too is whether the values to be remapped represent module ids or prefixes.  eg:
map: {
  pkgA: {
    foo: "foo1.2"
  }
}

if pkgA depends on "foo/bar" should it get "foo1.2/bar"?

i know how i would like all of this to work but i don't want to make assumptions based on how i'd like it to work.  i don't see these clearly spelled out in the spec and i can see that it would be easy for different people to make different interpretations.  hopefully we can avoid some frustration later by clarifying this now.

ben...

James Burke

unread,
Jul 16, 2012, 8:44:57 PM7/16/12
to amd-im...@googlegroups.com
Away from computer, but two notes:

* I meant to remove map from the package area, bad copy paste. Map is its own config section.
* map in requirejs is similar to paths: it I applied to to any module ID prefix match, so it should meet your use case concern.

I apologize for not scrubbing the text better. I will update that draft with the above, but it may take a day or so.

James

Rawld Gill

unread,
Jul 16, 2012, 9:16:44 PM7/16/12
to amd-im...@googlegroups.com
That works for me. I'll update the dojo impl later tonight. Unless we run into problems, it will make 1.8.

--Rawld

> -----Original Message-----
> From: amd-im...@googlegroups.com [mailto:amd-
> impl...@googlegroups.com] On Behalf Of James Burke
> Sent: Montag, 16. Juli 2012 17:45
> To: amd-im...@googlegroups.com
> Subject: [amd-implement] Re: Common configuration draft
>

James Burke

unread,
Jul 17, 2012, 8:37:55 PM7/17/12
to amd-im...@googlegroups.com
On Mon, Jul 16, 2012 at 5:44 PM, James Burke <jrb...@gmail.com> wrote:
> * I meant to remove map from the package area, bad copy paste. Map is its
> own config section.

It is now removed from the wiki page.

> * map in requirejs is similar to paths: it I applied to to any module ID
> prefix match, so it should meet your use case concern.

The map section has some text about this already, and an example.

Ben, if you think that section could be worded better, I'm open to
ideas. And of course if I completely misread your concern, clue me in.
:)

James

Richard Backhouse

unread,
Sep 4, 2012, 9:05:58 AM9/4/12
to amd-im...@googlegroups.com
I'm in the process of implementing the  Map Config support and wanted to double check on something.

The spec states :

" Object. Specifies for a given module ID prefix, what module ID to use in place of another module ID"

I just want to be sure that we are talking specifically about "module ID" and not "module ID prefix" for the values in the mapEntry. For example

{
    map: {
        'some/newmodule': {
            'foo': 'foo1.2'
        },
        'some/oldmodule': {
            'foo': 'foo1.0'
        }
    }
}
foo, foo1.2 and foo1.0 are module ID's and not module ID prefixes correct ?

Also, this is directed to James. Are you supporting Map Configs in r.js ? For my optimizer it has become quite involved on how to tackle the issue of the multiple modules defining themselves with the same id within the same delivered javascript stream.

Richard

James Burke

unread,
Sep 4, 2012, 9:13:59 PM9/4/12
to amd-im...@googlegroups.com
On Tue, Sep 4, 2012 at 6:05 AM, Richard Backhouse
<richarda...@gmail.com> wrote:
> I'm in the process of implementing the Map Config support and wanted to
> double check on something.
>
> The spec states :
>
> " Object. Specifies for a given module ID prefix, what module ID to use in
> place of another module ID"
>
> I just want to be sure that we are talking specifically about "module ID"
> and not "module ID prefix" for the values in the mapEntry. For example
>
> {
> map: {
> 'some/newmodule': {
> 'foo': 'foo1.2'
> },
> 'some/oldmodule': {
> 'foo': 'foo1.0'
> }
> }
> }
>
> foo, foo1.2 and foo1.0 are module ID's and not module ID prefixes correct ?

Ah, I treat them as module ID prefixes. That makes it more fun doesn't
it? :) I think it makes sense though, particularly for cjs-type
"packages". If someone asks for "foo/helper", seems like that should
translate to "foo1.0/helper" for oldmodule.

I need to work up some tests to include in the amdjs test set for this
common config now that we have a few folks implementing them. I'll try
to get it done next week. In the meantime, here are the tests I use in
requirejs:

https://github.com/jrburke/requirejs/tree/master/tests/mapConfig

The r.js optimizer does builds and places them in the "built" folder
in there as part of its unit tests, if you wonder where they come
from. The r.js map build tests start here and are their names start
with "map":

https://github.com/jrburke/r.js/blob/master/build/tests/builds.js#L998

> Also, this is directed to James. Are you supporting Map Configs in r.js ?
> For my optimizer it has become quite involved on how to tackle the issue of
> the multiple modules defining themselves with the same id within the same
> delivered javascript stream.

I do support them in r.js, at least to the extent that the above tests
pass. If you have a tricky test case though, I am interested to see
it.

James

Richard Backhouse

unread,
Sep 8, 2012, 8:37:12 AM9/8/12
to amd-im...@googlegroups.com
Thanks for the clarification.

I think it would be best to modify the text in the spec to avoid confusion. Perhaps changing the wording to :

"Object. Specifies for a given module ID prefix, what module ID/prefix to use in place of another module ID/prefix"

What do you think ?

I took a look at the tests you have in requirejs and converted a few of them over to run in amdjs-tests. I took "mapConfig", "mapConfigStar" and "mapConfigStarAdapter". The others seemed to be more requirejs specific.

The "mapConfigStar" test has highlighted another gotcha (at least for me with the approach I have taken).

There is a map configuration of

        '*': {
            'c': 'another/c'
        },

The 'another/c' module has a peer reference to a module called './minor' so the full mapped id for it would be 'another/minor'. At the moment the approach I have taken is not modify the ids that are written into the modules. That is they are in unmapped form. This results in multiple define calls with the same id. To handle this I add the matched mapping as an additonal parameter to the define call and that is used to better qualify the id of the module internally. With this approach I don't have to mess with the dependent list to modify the mapped id there too. This works for mapped ids and prefixes but the peer module has caused me problems. Looking at your built version of the "mapConfigStar" test I see that your code writes in the mapped ids. I'm curious to know if you also modify the modules dependency lists too for these mapped ids.

Richard

Richard Backhouse

unread,
Sep 8, 2012, 8:51:34 AM9/8/12
to amd-im...@googlegroups.com
So it just dawned on me that the dependency list ids don't have to be modified as the only one that are affected as the relative ones and they don't need to be changed :-). I think my current approach is overdoing things.

Richard Backhouse

unread,
Sep 8, 2012, 1:52:10 PM9/8/12
to amd-im...@googlegroups.com
After realizing my originally approach was overly complex and also doomed to failure I have ended up with a much simpler solution that passes the 3 mapConfig tests, "mapConfig", "mapConfigStar" and "mapConfigStarAdapter" :-)

James, if it helps I can fork the amdjs-tests repo and create a push request with these 3 tests I've added.

Richard

James Burke

unread,
Sep 11, 2012, 2:13:48 PM9/11/12
to amd-im...@googlegroups.com
On Sat, Sep 8, 2012 at 10:52 AM, Richard Backhouse
<richarda...@gmail.com> wrote:
> James, if it helps I can fork the amdjs-tests repo and create a push request
> with these 3 tests I've added.

That would be awesome!

I also updated the config page to what you suggested, but instead of
"ID/prefix" I just said "ID prefix". So:

"Object. Specifies for a given module ID prefix, what module ID prefix
to use in place of another module ID prefix"

James

Richard Backhouse

unread,
Sep 11, 2012, 3:11:54 PM9/11/12
to amd-im...@googlegroups.com
James,

Here is the pull request :

https://github.com/amdjs/amdjs-tests/pull/10

Richard

James Burke

unread,
Sep 11, 2012, 3:28:32 PM9/11/12
to amd-im...@googlegroups.com
On Tue, Sep 11, 2012 at 12:11 PM, Richard Backhouse
<richarda...@gmail.com> wrote:
> https://github.com/amdjs/amdjs-tests/pull/10

Thank you, merged! I also updated the README to mention the
availability of these new tests.

James

Mike Wilson

unread,
Jul 22, 2013, 8:46:02 AM7/22/13
to amd-im...@googlegroups.com
The Common Config spec is still draft, but is it possible to say what parts that seem to have general agreement among implementors?
ATM I'm specifically interested in the config() stuff, but it'd be interesting to hear about the rest too :-)

Thanks
Mike

James Burke

unread,
Jul 23, 2013, 6:56:52 PM7/23/13
to amd-im...@googlegroups.com
Looking at amdjs-tests, it looks like these loaders support the
following config:

inject:
"paths"

requirejs & zazl:
"map"
"module"
"packages"
"paths"
"shim"

curl and dojo are not in the test suite so I cannot speak to them.

"map" config came from a dojo concept, but it was a bit different, not
sure if it is supported as "map" as mentioned in that draft in dojo.

I'm open to marking some of those config options as non-draft, but
feel the other implementers need to agree, and in particular, we would
have them in the tests and passing them before moving them out of
draft.

James
> --
> You received this message because you are subscribed to the Google Groups
> "amd-implement" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to amd-implemen...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>

Mike Wilson

unread,
Jul 23, 2013, 8:43:30 PM7/23/13
to amd-im...@googlegroups.com
Thanks James,

I can see that module.config() is covered in the module test but it would of course have been nice to know about more implementations. I checked the Dojo source and found some code (line 1548 of https://github.com/dojo/dojo/blob/1.9.1/dojo.js) defining this config() function so it seems they are on-board. Haven't tried it yet though.

BTW, while looking for info I found this statement:
packageMap, paths, and aliases properties, they are all deprecated - map is the configuration option to use moving forward
on http://dojotoolkit.org/documentation/tutorials/1.9/modules_advanced/, which even links to the Common Config draft.
But http://dojotoolkit.org/reference-guide/1.9/loader/amd.html still doesn't mention it.

Best regards
Mike

Ed Swift

unread,
Jul 12, 2014, 4:00:33 AM7/12/14
to amd-im...@googlegroups.com
Where is this configuration info supposed to go? Couldn't find anything addressing that in the draft. Is it up to the implementation?  If so, does it make sense to have it as a property of define.amd, either as a function taking a configuration object or as a plain old object?

James Burke

unread,
Jul 13, 2014, 1:25:48 AM7/13/14
to amd-im...@googlegroups.com
On Sat, Jul 12, 2014 at 1:00 AM, Ed Swift <doo...@gmail.com> wrote:
Where is this configuration info supposed to go? Couldn't find anything addressing that in the draft. Is it up to the implementation?  If so, does it make sense to have it as a property of define.amd, either as a function taking a configuration object or as a plain old object?

As the config is for the loader, it should be off of the loader’s top level loader API. If the loader supports a global require called `require`[1], then require.config() is something other loaders have chosen.

`define` is the declarative module definition API.


James

Ed Swift

unread,
Jul 13, 2014, 1:59:59 AM7/13/14
to amd-im...@googlegroups.com

As the config is for the loader, it should be off of the loader’s top level loader API.

Thanks for your reply. My loader doesn't have a top-level API, it only defines a global variable `define`. So technically I guess `define` is the top-level API. Given that the entire API is a global `define` function, do you think a `define.amd.config` function is alright?
 
If the loader supports a global require called `require`[1], then require.config() is something other loaders have chosen.

My loader doesn't support a global `require`. If `define.amd.config` is no good, is there anywhere else it could live?

James Burke

unread,
Jul 13, 2014, 2:21:36 AM7/13/14
to amd-im...@googlegroups.com
On Sat, Jul 12, 2014 at 10:59 PM, Ed Swift <doo...@gmail.com> wrote:

As the config is for the loader, it should be off of the loader’s top level loader API.

Thanks for your reply. My loader doesn't have a top-level API, it only defines a global variable `define`. So technically I guess `define` is the top-level API. Given that the entire API is a global `define` function, do you think a `define.amd.config` function is alright?


There should to be some way to kick off the resolution of modules, besides just define(). define() calls by themselves should just register the existence of a module definition, but not immediately execute the factory function. That will more closely match expectations that people have from other loaders and how it more closely matches the behavior of dynamically loaded modules, whose factory functions are only called because they are part of a top level load dependency tree.

 
If the loader supports a global require called `require`[1], then require.config() is something other loaders have chosen.

My loader doesn't support a global `require`. If `define.amd.config` is no good, is there anywhere else it could live?


You are free to put it wherever you would like then. It will likely just be very non-standard, but top level load APIs often are, as they are under the loader’s name. For instance, for requirejs, there is a requirejs.config() at the top level. As mentioned above, it is hard to see having a loader without a loader API to kick off loading, as define() was not designed for that.

James


 

Ed Swift

unread,
Jul 13, 2014, 2:44:57 AM7/13/14
to amd-im...@googlegroups.com
There should to be some way to kick off the resolution of modules, besides just define(). define() calls by themselves should just register the existence of a module definition, but not immediately execute the factory function. That will more closely match expectations that people have from other loaders and how it more closely matches the behavior of dynamically loaded modules, whose factory functions are only called because they are part of a top level load dependency tree.

The way my loader works, factories are executed as soon as all dependencies are loaded. I just assumed this was how it was supposed to work from reading the spec. So if you have something like this at the top level:

    define(['foo', 'bar'], function(foo, bar) {
        // do stuff
    })

...as soon as `foo` and `bar` and all their dependencies are ready (factories have run and modules have export values), this factory will run. Of course it goes without saying that a call to `define` with no dependencies will run the factory immediately (whether it's at the top level or not). 

It seems to work pretty nicely so far. I'm not sure I see the need for a separate function to kick things off, but I don't want to derail this thread any more than I have. Maybe I'll start a new thread about this.

Mike Wilson

unread,
Jul 14, 2014, 8:37:07 AM7/14/14
to amd-im...@googlegroups.com
Hi James,
 
James Burke wrote:
As the config is for the loader, it should be off of the loader’s top level loader API. If the loader supports a global require called `require`[1], then require.config() is something other loaders have chosen.
What about the
    require({
        options...
    });
syntax?
 
At least for a while I thought that was the portable loader setup style :-)
Still valid, or deprecated?
 
Best regards
Mike

Mike Wilson

unread,
Jul 14, 2014, 8:54:20 AM7/14/14
to amd-im...@googlegroups.com
Hi Ed,
 
Your reasoning works fine as long as every code module you use may be associated with a name, so another code module can refer to it by this name (an AMD "define" will give your module an identifier implicitly or explicitly).
Eventually though, you may discover that you would like to have "anonymous" code modules that import other modules but don't export themselves. It is more common that this desire comes out of convenience rather than security, f ex when inlining code in a web page or other scenarios where the consumer of your module isn't already itself a defined AMD module. This is when you use "require".
So yes, your project will probably have more defines than requires, but there are still use-cases for require.
 
Best regards
Mike Wilson
Reply all
Reply to author
Forward
0 new messages