~Daniel Friesen (Dantman, Nadir-Seen-Fire) [http://daniel.friesen.name]
If you'll have some patience to examine the information on this link:
http://groups.google.com/group/jsan/browse_thread/thread/8035ed10b2e6750c# ,
> These may interest you (in regards to using XMPP):
> http://metajack.im/2009/03/12/awesome-demo-of-real-time-xmpp-powered-app/
> http://code.stanziq.com/strophe/
Very cool.
> I have formulated some ideas (enough to convince myself that your
> goals are very achievable) regarding this topic. I would also be
> interested in starting a google group on this subject if many of you
> are interested.
I am interested. Specifically built on top of narwhal [1] which has a
browser engine for loading modules in the works.
Christoph
[1] - http://www.narwhaljs.org/
I'm using the name "require" in my efforts, since it's guaranteed to
be masked by the module constructor function. It's also usable as a
function, the sandbox object, for invoking requests for modules by
their top level identifier. In one of my prototypes, I'm using
"require.regsiter(topId, factory)" for script injection.
> For these reasons, I have a slightly different module-wrapping syntax
> to propose.
> modules = {
> "{{script1_name}}": function(require, exports) {
> {{script1}}
> },
> "{{script2_name}}": function(require, exports) {
> {{script2}}
> },
> ...
> };
>
> When the <script> loads, an onload handler fires, snags
> window.modules, iterates over its properties, saving the name-value
> pairs for lazy access via require("script_nameN"). Yes,
> window.modules will get clobbered over and over again, but the trick
> is that the onload handler examines it (and maybe even deletes it)
> immediately after the script defines it.
That's one strategy. One disadvantage of it is that the line numbers
and file names don't work out for debugging. One of my prototypes
grabs individual scripts en masse with individual requests. That's
pretty good, and also pretty fast, for development purposes when you
can collude with the server. For production, I am also going to do a
version that bundles and minifies all the transitive dependencies. It
will also use require.{{method}} machinery.
> As far as I can tell, this protocol addresses the multiple-independent-
> loader and hijacking concerns I raised above. If that claim seems
> unjustified (or unclear), please speak up.
One nice thing about Chiron is that you can have multiple independent
loaders on the same page. It has no footprint on global scope. The
only way to accomplish this is with XHR. Chiron uses sync XHR, but a
non-global asyc XHR with bundles or individual scripts can also be
constructed.
I've written up some tickets for myself on Narwhal [2]. It's clear
that no single module loader will be perfect for any particular
scenario (with/without server colusion, development/production,
with/without loader availability to later inline scripts), but we can
provide a loader for each person's requirements and a handy matrix to
help them choose. I've written up a couple tickets to this end on
Narwhal and plan to spend some time on it this weekend [1].
In any case, the proper venue for this kind of discussion is certainly
closer to implementation than specification. I welcome anyone
interested in Narwhal's implementation to join me on our mailing list
[6]
I've presently implemented two loaders for Narwhal; one that uses an
inline script [4] to inject the transitive dependencies of a given
module and then load that module, and a port [5] of Chiron's
modules.js that uses the server component to grab the module file
corresponding to its top level id. Both implementations uses a
prototype "narwhal/server" JSGI app [3].
The only issue that's relevant to standardization is that most of
these browser loaders will depend on static analysis to discover the
transitive dependencies of a module, and the trouble is that there is
no safe synchronous solution for loading "dynamic dependencies".
"require", as specified, is a synchronous operation. For dynamic
dependencies, we will need to eventually specify
a variant on "require" for the asynchronous load case. I'm presently
favoring "require.async(id)" -> promise, and *allowing* the
synchronous "require(id)" to throw an error if the module cannot be
loaded synchronously, which may only happen if the id is not a String
literal.
Kris Kowal
[1] http://github.com/tlrobinson/narwhal/issues/labels/re-modules
[2] http://github.com/tlrobinson/narwhal/issues/labels/re-modules#issue/22
Ah, yes, very apt. I believe we would have reasonable flexibility if
modules were bundled as a sequence of zero or more calls to
require.register(topId, function (require, exports) {…}); This would
be more like JSONP than JSON, as we would need (in some cases) the
callback to notify the loader that the module has arrived and been
registered.
Kris Kowal
This convinces me that the JSONP approach would not be feasible for
module factory registration. JSONP is typically used for dynamic or
un-cache-able data. Modules should be cache-able. One of our goals
should be to post modules to a CDN. To that end, I think static
padding is desirable.
I concur that registration must be lazy. Module factory functions
must not be implicitly promoted to module instances. Doing so would
non-deterministically break cyclic dependencies, and even more
frequently would cause modules to be loaded before their dependencies
were registered.
My purpose for recommending that a function call for each module
factory registration is to simplify bundling. We could have the best
of both worlds with a signature of require.register(modulesMemo);
bundle : = registerCall*;
registerCall := "require.register(" + moduleFactoryMemo + ")";
moduleFactoryMemo := "{" + ((stringLiteral, ":", moduleFactory)
delimited-by ",") + "}";
moduleFactory := "function(require,exports,module){" + moduleText + "}";
So, here's my summary of our progress:
* we agree that modules must be lazy
* we agree that modules must be cache-able
* therefore, the padding or template for a module bundle must be static
* you want and i'm willing to support multi-entry module memo registration
* i want the ability to concatenate bundles (i presume you have no objection)
Kris Kowal