@deitch-
I see the problem differently. I would say that the fundamental problem of
a client-side module loader is exactly the same as that of a server-side
one:
1) Allow me to write really modular reusable code, without artificial
restrictions.
The client-side module loader has a lot of domain-specific implementation
details that differ from the server-side. The answer to these should be to
hide the ones that developers can't use for their advantage, as much as
possible, and provide easy-to-use syntax for the ones that they can use for
their advantage, or really need to know about and take into consideration.
Example of the first kind:
Dynamic optimization/caching are things that we want, but shouldn't have to
think about
Example of the second kind:
In large web app, a developer knows as he's writing the app that some thing
will not happen until a user clicks something, or may never happen. So
never loading that code until it is needed is an advantage. In other cases
a certain portion of the app needs a bunch of dependencies immediately, so
loading them all in separate server calls doesn't make sense.
To handle those two cases, we have a simple syntax of synchronous vs. async
require statements.
The examples are probably the easiest way to understand how it works.
On Tuesday, March 27, 2012 4:24:07 AM UTC-7, deitch wrote:
>
> @meelash,
>
> I am pretty sure I get the basic concept, not the details, so hard to
> comment.
>
> Let me rephrase how I understand the problem, and then maybe you can help
> explain how it solves it?
>
> On server-side, I just require(modulename) and get it. It is easy, and
> every module can require whatever it needs.
>
> On client-side, I have two problems:
> a) Within a file, I cannot do require, the module (i.e. .js file) needs to
> assume whatever it needed was loaded.
> b) I actually need to load the file separately, either through <script
> src="foo.js"></script> or using a loader like labjs.
>
> It sounds like you are trying to solve these in one fell swoop, by
> including one file, say <script src="specialloader.js"></src> or whatever,
> and having that then load all the others. However, rather than (a) fileA.js
> assuming the contents of fileB.js (which it needs) have already been loaded
> and (b) manually creating a script tag to include fileB.js, you are doing
> something inside fileA.js that is then parsed by a middleware on the server
> side? If so, how do I do it, and how do I not break the traditional
> client-side?
>
> Truth is, browsers desperately need a "require()" function, so that a
> script can just load other scripts...
>
>
>
>
>
> On Sunday, March 25, 2012 2:04:52 AM UTC+2, meelash wrote:
>>
>> tl;dr - Client-side require with a server-side component that caches
>> dependencies, bundles them, and caches the bundles. Need feedback on
>> the concept, syntax. Need suggestions/contributions on implementation.
>> Although, this works for me, it is almost just a proof-of-concept,
>> needs work.
>>
>>
>> As part of a project I'm working on, I spent a few hours writing a
>> little client-side module loader with a server-side component enabling
>> what I think is a pretty neat meaning to CommonJS module syntax. This
>> morning I pulled it out of the rest of my project and attempted to
>> package it in a useful way for others to use.
>>
>> The basic idea is this- in your client-side code, you can use require
>> in either a "synchronous" or asynchronous fashion-
>> module1 = require('some/path.js');
>> require('some/other/path.js', function(err,result){module2 =
>> result;});
>>
>> An asynchronous require makes a call to the server component to get
>> the file in question, but before returning the file, the server parses
>> it, finds all the synchronous require calls, loads those files as well
>> and returning the whole thing as a package. That way, when the
>> original file that was asynchronously loaded is executed and comes to
>> one of those synchronous require calls, that file is already there,
>> and the require is actually synchronous.
>>
>> At this point, maybe this screencast demo will help to clarify how it
>> works: http://screencast.com/t/nOU53BRYUAX
>>
>> Put another way:
>> If I async require fileA, and fileA has synchronous dependencies on
>> fileB, and fileC, and an asynchronous dependency on fileD, the server-
>> side component will return (in a single "bundle") and keep in memory
>> fileA, fileB, and fileC, not fileD, and it will execute fileA.
>> The client-side also separates fetching the files and eval'ing them
>> (the method of getting files is xhr+eval). So, let's say fileA has
>> require('fileB'); that executes when the file is parsed and executed
>> on the client, but require('fileC') is inside a function somewhere.
>> Then fileA will first be eval'ed, then fileB when it comes across
>> that, and the text of fileC will just be in memory, not eval'ed until
>> that function is called or some other require to it is called by any
>> other part of the program.
>>
>> Another example-
>> fileA has dependencies fileB, fileC, fileD, fileE, fileF
>> fileG has dependencies fileC, fileE, fileH
>>
>> When I call require('fileA', function(err,result){return 'yay';});,
>> the module loader will load fileA, fileB, fileC, fileD, fileE, and
>> fileF all in a single bundle.
>> If I, after that, call require('fileG', function(err,result){return
>> 'yay';});, the module loader will only load fileG and fileH!
>>
>> Hopefully, that's clear....
>>
>> The advantages-
>> Being aware of the difference in synchronous and asynchronous require
>> in your client-side code make it extremely natural to break all your
>> client-side code into small reusable chunks- there is no penalty and
>> you don't have to "optimize" later by deciding what to package
>> together and what to package separately.
>> Handling dependencies becomes nothing. You don't have to think about
>> it.
>> The server can have a "deployment" mode, where it caches what the
>> dependencies of a file are and doesn't ever need to parse that file
>> again.
>> In "deployment" mode, the server can also cache bundles of multiple
>> files that are requested together, so when another client requests
>> that same bundle, it is already in memory.
>>
>> To sum up:
>> xhr+eval-when-necessary client-side module loader
>> both synchronous-ish and asynchronous require in your client side-code
>> --the synchronous require is actually a command to the server-side
>> component to bundle
>> server-side component
>> --parses for dependencies and bundles them together
>> --can cache dependency parsing results and whole bundles
>>
>>
>> So- thoughts? Is this a horrible idea? Are there some gotchas that I'm
>> missing?
>>
>> Specific advice needed-
>> • How to package this in a way that it can be easily used in other
>> projects? How can I make it integrate seamlessly with existing servers
>> and make it compatible with different transport mechanisms?
>> • How to handle path resolution?
>> • Suggestions for licensing?
>> • Suggestions for a name- (Mundlejs is a portmanteau of Module and
>> Bundle- didn't really think long about it)
>>
>> Things that need to be (properly)implemented:
>> • server-side "parsing" is just a brittle regexp right now:
>> (line.match /require\('(.*)'\)/)
>> • neither type of server-side caching is implemented (pretty easy to
>> do)
>> • uniquely identify clients and keep the server away of what modules
>> they already have, so we can just send the diff of cached modules-
>> currently, I'm sending the entire list of already cached modules with
>> every xhr call, so the server doesn't load a dependency twice.
>> • proper compatibility with module specifications (i.e. CommonJS)-
>> right now, it's just require and module.exports
>>
>>
>> Code is available here: https://github.com/meelash/Mundlejs
>> To test it:
>> from Mundlejs/tests/, run
>> node server.js
>> visit http://127.0.0.1:1337/ and open your browser console.
>
>
--
Job Board: http://jobs.nodejs.org/
Posting guidelines:
https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
You received this message because you are subscribed to the Google
Groups "nodejs" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/nodejs?hl=en?hl=en