[dojo-contributors] Asynchronous Module Definition (was Re: [CommonJS] Another idea on unifying Transport/C and /D)

Kris Zyp kzyp at dojotoolkit.org
Tue Oct 12 14:45:21 EDT 2010

On 10/12/2010 11:22 AM, James Burke wrote:

> > On Sun, Oct 10, 2010 at 3:05 PM, Kris Zyp <kriszyp at gmail.com> wrote:
>> >> Of course, I understand that RequireJS can't eliminate "require", since
>> >> it is a core API for it. However, needing to have two globals is hardly
>> >> going to get much sympathy from me, especially considering that the
>> >> whole module system eliminates the need for developers to be fighting
>> >> for globals at all. Back in the ol' days when we used archaic namespaces
>> >> hung off globals this was a bigger issue. Now we could have dozens of
>> >> globals without impacting the module system. EcmaScript itself defines
>> >> dozens and the typical browser environment has hundreds of globals. Plus
>> >> globals used without any community coordination (libraries grabbing
>> >> common names as globals without namespacing) is the biggest source of
>> >> possible conflict, but this is completely the opposite, it is totally
>> >> being done as a community, and is exactly the *right* way to establish
>> >> globals. One or two (community ascribed) globals should hardly be a concern.
> > My concern was more for browser code that gradually adopts the
> > require/define approach. I believe that will allow for quicker/broader
> > adoption if existing code can use this new functionality gradually, so
> > fewer globals are better. I also agree that if push came to shove,
> > then two vs one global is not that much of a change, but the proposed
> > renaming to me did not seem to give that much benefit to warrant
> > another global.
> >
Again, the suggestion is that CommonJS only define a single global not
two. In fact this should actually improve the conflict/pollution
potential of RequireJS. If RequireJS uses a community global (require or
define) and defines its own APIs on it, it is effectively polluting the
global/shared namespace with possible name conflicts just as much as if
it defines all its APIs directly on window. By putting modify(),
version, plugin(), isBrowser, baseUrl, etc. on a shared object
"require", you are injecting into a shared space. "require"'s can have
conflicts just like "window". By claiming that you are not using globals
because it is under require is a silly name game, it is still shared. If
CommonJS only defines a global "define" than RequireJS can use a single
namespace under require (since "require" would be free then) and keep
its own API separate from the shared namespace. This is the right way to
avoid conflicts (which is the point of avoiding global pollution,
whether it be the "window" global or any other shared namespace).

Likewise, for Dojo, we should be defining any Dojo specific module loader settings and initiation actions on the dojo.* namespace, and absolutely *not* on the CommonJS shared namespace.

>>> >>> I also do not think define.ensure makes sense -- it really means a
>>> >>> kind of "require" vs a "define" -- the script requires that these
>>> >>> other scripts/modules are available before running the function.
>> >> Its no less logical than require.def, whose purpose is to define a
>> >> module. This is all about frequency. If every single module using the
>> >> module definition API, but only a call or two that does the initial
>> >> require (require([]) or define.ensure()), it makes sense to give the
>> >> more frequently used form the most elegant logical API. Or we could have
>> >> a "define" and have a global "require" like RequireJS's.
> >
> > I believe require.def is more logical than define.ensure. require.def
> > implies you are defining something that obeys require's rules.
> > define.ensure does not define anything. But this is a bit of a
> > bikeshed.
After thinking about this, there really is no reason CommonJS needs to
define a define.ensure, I recant that suggestion. The point of
require.ensure is to provide an interoperable way for modules to load
other modules on demand. The ensure() API is not needed for the initial
entry loading of modules, the initiating the module loader is always
module loader specific anyway, so it is fine to a module loader specific
API to do the initial launch of modules. Since ensure() is intended for
modules, it can continue to exist as a property of the "require" free
variable, without any need for a "require" global. RequireJS's use of
the require() global to launch modules makes perfect sense, and is
fantastic module loader specific API without any need for definition
from CommonJS.

> >  
> >
>> >> But RequireJS doesn't even implement require.ensure, does it? It doesn't
>> >> seem like this would affect RequireJS.
> > I have not implemented it because no one has asked for it when using
> > RequireJS, and I think it is inferior to the require([]) syntax that
> > RequireJS provides. However, if it enabled widespread async module
> > adoption (vs RequireJS require([]), then I would implement it, since
> > it is a subset of what require([]) can do now.
Yeah, I could see there not being much demand for require.ensure.

>> >> I think the main reason this is worth considering is that it affects
>> >> *every single* module (and the byte count thereof, which quickly adds up
>> >> for apps with many modules), so it is worth taking a hard look at what
>> >> is best here even if there might mean some API change pain.
> > I do not believe byte size count matters for performance reasons (with
> > an optimized, minified delivery of modules with gzip, it will be
> > unnoticeable), but I appreciate wanting the cleanest API.
> >
> > I am voting "no" though, I do not believe it buys that much for the
> > following reasons:
> > - inertia. Mostly my personal inertia. It does not feel broken to me.
> > - I also like the single global. It still makes sense to me that an
> > ensure stays on require, or even better, just uses require([]) as used
> > by RequireJS. That means the define name space just defines an async
> > module, and an async module implementation still needs to implement
> > something for "require".
> > - I like that require.def implies that it obeys require's rules.
> > define seems to float out in the ether.
> >
> > If others feel strongly, that require.def is just wrong, then I can
> > support a define that maps to require.def in RequireJS. But others
> > should speak up soon, as in the next couple of days. I want to move on
> > to implementations and adoption.
> >
Yeah, I'd like to hear from others too.

-- Thanks, Kris

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.dojotoolkit.org/pipermail/dojo-contributors/attachments/20101012/001eb460/attachment.htm 

More information about the dojo-contributors mailing list