Dependency manager with CJS baked in

77 views
Skip to first unread message

rob.robb.ns

unread,
Dec 18, 2010, 11:48:31 AM12/18/10
to ControlJS
I'm going to attempt to roll up a dependency manager which will write
CJS script tags based on require() calls, a la' Closure or Dojo.

I have a working dependency manager, script loader now based on
Closure's, but instead of being a development-only tool which is
stripped away in a compilation pass this would remain through
deployment.
Anyone tried this yet?

It should either be a smashing success or blow up completely in my
face ;). No fence-sitting on this one.

Steve Souders

unread,
Dec 18, 2010, 1:02:50 PM12/18/10
to cont...@googlegroups.com, rob.robb.ns
It would be great if the require() calls happened as early as possible
in order to get the downloads to start sooner than later. A cool feature
of this would be to have dependencies across multiple scripts that
weren't parsed&executed until needed - so you might need carousel.js and
when that was injected (CJS.execScript("carousel.js")) the entire chain
of dependencies would be loaded (core.js, widget.js, etc.).

If we add this feature we'll need to have an "already loaded" state so
ControlJS doesn't document.createElement('script') a script that's
already been loaded in the page. (For example, we might have already
loaded "core.js" so don't want t inject it again during the loading of
carousel.js's dependencies.)

-Steve

rob.robb.ns

unread,
Dec 18, 2010, 3:23:43 PM12/18/10
to ControlJS
So far the top level object (called 'I' at this point) keeps a hash of
provides, requires, and what has already been written to the page.

So,
"I.require('carousel');"
would result in a tag like,
<script type="text/cjs" cjssrc="now/plugins/carousel.js"></script>.
If you had a directory named plugins with the file carousel.js in your
source directory.

I have a Node.js program about 1/2 the way done that scans your source
directory (like 'scripts/')
and writes a file (think Closure's calcDeps.py) depending on what it
finds, for example if your folders were like so:

scripts/
---control.js
---i.js
---now/
---jquery.js
---plugins/
---carousel.js
---later/
---foo.js

A dependency file would be written containing calls to
I.addDependency() like,
I.addDependency('scripts/now/jquery.js', 'jquery', false);
I.addDependency('scripts/now/plugins/carousel.js', 'carousel', false);
I.addDependency('scripts/later/foo.js', 'foo', true);

which would cause the tags:
<script type="text/cjs" cjssrc="scripts/now/jquery.js"></script>
<script type="text/cjs" cjssrc="scripts/now/plugins/carousel.js"></
script>
<script type="text/cjs" cjssrc="scripts/later/foo.js" cjsexec=false></
script>
to be rendered

the now/ and later/ directories are being used to tell the node.js
depWriter program
if the bool for cjsexec should be set or not.

The i.js file should only be a few k when minified, looks like its
around 90 lines @ about 90% done.
ATM I am loading it blocking, it then writes the async script to fetch
control.js then checks the dependency file

rob.robb.ns

unread,
Dec 18, 2010, 3:35:44 PM12/18/10
to ControlJS
Oh, the tags would obviously only get written if you had a script with
a I.require('foo') in it.
the 'deps.js' file (written by the node.js depWriter) is just so that
i.js knows where 'foo' is.
I.require keeps track of the files and won't load the same one twice.

Will Alexander

unread,
Dec 18, 2010, 3:50:06 PM12/18/10
to ControlJS


> I.addDependency('scripts/now/jquery.js', 'jquery', false);

> <script type="text/cjs" cjssrc="scripts/now/jquery.js"></script>

> the now/ and later/ directories are being used to tell the node.js
> depWriter program
> if the bool for cjsexec should be set or not.

What does the third parameter to addDependency() do?

rob.robb.ns

unread,
Dec 18, 2010, 4:07:27 PM12/18/10
to ControlJS
if true it would add 'cjsexec=true'.
on my dev box I am experimenting with 'now/' and 'later/' directories
in my 'scripts' folder.
any file in the 'later/' directory would get the third param set to
true.

i may ditch the idea, it's early yet...

rob.robb.ns

unread,
Dec 18, 2010, 8:45:43 PM12/18/10
to ControlJS
dammit! Let's try that again...
if true it would add "cjsexec=false".

In other words a true in that spot adds the 'cjsexec=false' attribute
to the tag, otherwise
that attribute isn't written at all (no need for a cjsexec=true)

Will Alexander

unread,
Dec 19, 2010, 12:45:07 AM12/19/10
to ControlJS
> dammit! Let's try that again...
> if true it would add "cjsexec=false".
Be careful or you could end up with the Unix shell: Anything that's
not non-zero is true :-)

Out of curiosity, would you be able to express dependencies on third-
party libraries? If so, have you given any thought to how those might
be loaded on the client?

rob.robb.ns

unread,
Dec 19, 2010, 3:05:49 PM12/19/10
to ControlJS
OK, I have a little working demo that I am going to put up a github
repo for....here's the link:
www.github.com/robrobbins/I

Will, the demo shows an answer to your question. The silly little
test.js file has a require('jquery').

Any js file can be loaded as long as there is an entry in the deps.js
for it. Right now you can add the entries into the deps.js file
yourself, but the forthcoming Node.js utility 'depwriter' will do this
for you. It scans your source file recursively looking for files with
a I.provide('foo') or I.require('bar') and writes the deps.js file
accordingly. My first version of i.js would simply ignore files with
no provide() or require() statements but that won't work for third
party libs so..

To deal with 3rd party libraries (like jquery for example) I am
thinking of using a directory convention, maybe a 'vendors' or
'thirdParty' which the 'depWriter' will automatically add an entry
into the deps file for. The deps file is used by require() to write
the cjs tags correctly (src and cjsexec)...

Thinking about it now I might as well just make that folder or folders
configurable in the Node.js depWriter itself. Tell depWriter which
directory or directories contain files that should get put into the
deps.js without being scanned.

I should have the depWriter done in the next few days. Like I said I
am just putting the entries into deps.js by hand ATM. See the source
for examples.

rob.robb.ns

unread,
Dec 19, 2010, 8:29:51 PM12/19/10
to ControlJS
http://www.github.com/robrobbins/I

The link was busted and I had left out some of the support files.
Should be there now

rob.robb.ns

unread,
Dec 21, 2010, 10:44:35 AM12/21/10
to ControlJS
Actually got to start stepping through both last night. Obviously to
successfully mesh the two I have some changes to make. Like removing
the script writing from i.js completely and calling cjs.downloadScript
from I.require etc...

lots of hacking to be done...
Reply all
Reply to author
Forward
0 new messages