Hi everyone, This is now available as Connect middleware.
On Saturday, March 24, 2012 5:04:52 PM UTC-7, Saleem Abdul Hamid 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 nodejs@googlegroups.com To unsubscribe from this group, send email to nodejs+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/nodejs?hl=en?hl=en