Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

schwern (1528)

schwern
  (email not shown publicly)
http://schwern.net/
AOL IM: MichaelSchwern (Add Buddy, Send Message)
Jabber: schwern@gmail.com

Schwern can destroy CPAN at his whim.

Journal of schwern (1528)

Sunday April 10, 2005
06:36 PM

JSAN: A HOWTO Guide

[ #24112 ]

JSAN: the JavaScript Archive Network [jay-san] (becaue CJSAN is unpronouncable and nevermind that the jsan.* domains are all taken).

The goal: JavaScript modules for browsers with as minimal a build/install system as possible.

The trick: Minimize the need for an @INC or build system by using the browser's existing capabilities.

include():

    <script type="text/javascript" src="/js/jsan/use.js"></script>
    <script type="text/javascript">
        include("js/foo.js");
    </script>

jsan.js gives you an include() function similar to what Torgo's bootstrap.js is doing, it just relies on the browser's own "script" tag. This include function does what you'd expect and a little more. It looks in some sensible local locations for the file, the URL the HTML file is in (./js/foo.js) and the document root (/js/foo.js). The exact locations searched for could be configurable in something like /js/jsan/inc.js. This is your basic include functionality.

use(): Now the fun begins. Notice how its /js/jsan/use.js?

    <script type="text/javascript" src="/js/jsan/use.js"></script>
    <script type="text/javascript">
        use("bar");
    </script>

use() is a little different than include(). Initially its similar to include("js/bar/use.js") and works the same way. Now you have "modules" in the sense of "a pile of related JavaScript files in one directory with a central load point and an INC path". But the INC path goes a little further. What if you don't have 'bar' installed? Then it tries http://www.jsan.org/use/bar/use.js.

[evil grin]

remote libraries: If I want to distribute something which depends on other modules you don't have to install those dependencies to use it! My code says "use('something')" and it gets loaded from the net if necessary. If you want to install the dependencies locally, you can. You don't even need to install anything, you can just reference JSAN directly. Fantastic for rapid prototyping.

    <script type="text/javascript" src="http://www.jsan.org/use.js"></script>
    <script type="text/javascript">use("some-jsan-module")</script>

It even can use the browser's cache to your advantage. If JSAN becomes popular and a lot of sites start using JSAN modules pulled directly from JSAN the browser's cache means those files are only downloaded once for all the sites which use it. If the browser has a JavaScript JIT then even better!

To avoid jsan.org being a central point of failure, even with mirrors and round-robin DNS, a set of mirrors would be built into /js/jsan/inc.js in case jsan.org failed. And if you don't trust jsan.org you can always just pull the files onto your local server.

versioning: Ovid's the one who figured all this out. Local versioning is a little problematic, but remote versioning is a snap. Watch.

    <script type="text/javascript" src="/js/jsan/use.js"></script>
    <script type="text/javascript">
        use("wibble", 13);
    </script>

That's shorthand for use("wibble", "> 13") like Perl does. So what happens? Let's start with remote versioning, that's easier. Its very simple. It just loads "http://jsan.org/use/bar?version=13" and lets JSAN deliver you the right file. This kicks the verisoning logic out of JavaScript and onto the JSAN server which is better equiped to do it, its not even worth discussion at this point how jsan.org implements that. Then you can have whatever complex versioning spec you like including things like "== 13" (version 13 and only 13) and "13..20" (versions 13 through 20).

Versioning on the local filesystem is a bit harder, and you'll see why an integer versioning system is used. Going with an only.pm installation style where modules get installed as module-version/ so wibble-13/. How do you find the latest version of something when you can't ls? You also don't want to have to load a module just to find out its the wrong version, you want to continue down the INC path.

Here's the best I've got at the moment. When you install a JSAN module it goes into a module-version/ directory. It also writes/adds to module/manifest.js which is just a list of what versions of the module are installed. Essentially a hard-coded ls. use() can then employ that list to figure out if the right version is installed or if it has to look further up the INC path.

The problem with that is it makes installing a JSAN module more than simply unpacking a tarball or zip file. I'd rather not have a build system at all, introduces cross-platform scripting nightmares.

One thought is that, largely, this versioning stuff is YAGNI particularly having multiple installed versions of the same module and modules which need a particular version. So perhaps each module would have a simple version.js file which jsan can load and examine to get the version without having to load the whole module. Then you can just install as module/ (ie. no version in the directory name) and go. Those few who really want multiple versions installed can do the module-version/ and module/manifest.js scheme which requires extra build/install magic.

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.