Module naming and declarations
jrburke at gmail.com
Wed May 1 12:07:29 PDT 2013
On Wed, May 1, 2013 at 8:28 AM, Tab Atkins Jr. <jackalmage at gmail.com> wrote:
> Central naming authorities are only necessary if you need complete
> machine-verifiable consistency without collisions. As long as humans
> are in the loop, they tend to do a pretty good job of avoiding
> collisions, and managing them when they do happen.
I would go further: because humans are involved, requiring a central
naming authority, like an URL, for module IDs are a worse choice.
There are subcultures that ascribe slightly different meanings to
identifiers, but still want to use code that mostly fits that
identifier but is from another subculture.
The current approach to module IDs in ES modules allows for that fuzzy
meaning very well, with resolution against any global locations
occurring at dependency install/configure time, when the subculture
and context is known. It would require more config, generate more
friction and more typing with runtime resolution of URL IDs.
Examples from the AMD module world:
1) Some projects want to use jQuery with some plugins already wired up
to it. They can set up 'jquery' to be a module that imports the real
jQuery and all the plugins they want, and then return that modified
jQuery as the value for 'jquery'. Any third party code that asks for
'jquery' still gets a valid value for that dependency.
With ES modules in their current form, they could do this without
needing any Module Loader configuration, and all the modules use a
short 'jquery' module ID.
2) A project developer want to use jQuery from the project's CDN. A
third party module may need jQuery as a dependency, but the author of
that third party module specified a specific version range that does
not match the current project. However, the project developer knows it
will work out fine.
The human that specified the version range in that third party module
did not have enough context to adequately express the version range or
the URL location. The best the library author can express is "I know
it probably works with this version range of jQuery".
If all the modules just use 'jquery' for the ID, the project developer
just needs one top level, app config to point 'jquery' to the
project's CDN, and it all works out.
An URL ID approach, particularly when version ranges are in play,
would mean much more configuration that is needed for the runtime
code. All the IDs would require more typing, particularly if version
ranges are to be expressed in the URLs.
It is best if the suggestions on where to fetch a dependency from a
globally unique location and what version range is applicable are done
in separate metadata, like package.json, bower.json, component.json.
But note that these are just suggestions, not requirements, and the
suggestions may vary based on the project context. For example,
browser-based vs. server-based, or mobile vs. desktop. Only the end
consumer has enough knowledge to do the final resolution.
It would be awkward to try to encode all of the version and context
choices in the module IDs used for import statements as some kind of
URL. Even if it was attempted, it could not be complete on its own --
end context is only known by the consumer. So it would lead to large
config blocks that need to be loaded *by the runtime* to resolve the
URL IDs to the actual location.
With short names like 'jquery', there is a chance to just use
convention based layout, which means no runtime config at all, and if
there is config, a much smaller size to that config than what would be
needed for URL-based IDs. Any resolution against global locations
happens once, when the dependency is brought into the project, and not
needed for every runtime execution. Plus less typing is needed for the
module IDs in the actual JS source.
In addition, the shorter names have been used successfully in real
world systems, examples mentioned already on this thread, so they have
been proven to scale.
More information about the es-discuss