Blog


Server-Side JavaScript with Jaxer

Imagine ripping off the visual rendering part of Firefox and replacing it with a hook to Apache instead - roughly speaking that's what Jaxer is.

Jaxer is a strange new hybrid application coming from the folks at Aptana (the makers of the quite-excellent web IDE). Literally, they took the Mozilla platform (which powers Firefox, Camino, etc.) and built a stateful platform on top of it.

You can imagine it as a browser that's able to render pages, modify them dynamically with JavaScript and the DOM, and even use JavaScript libraries with great ease - with the exception that it's living as a standalone server-side process, un-associated with the typical browsing experience.

Aptana has implemented something that's greatly interested me ever since I started playing with JavaScript on the server-side (via Rhino). My friends over at AppJet even took a step towards making this concept easy, hosted, and free. The difference here is the severe amount of power and leverage that you're gaining with this platform: file I/O, network connectivity, database access, and even email access.

Let's back up a bit and look at an example of a simple, but representative, Jaxer application. This simple application is a textarea which, when submitted, quietly saves the results to a text file on the server. What you see below is the entire application - there is no other server-side language being used save for JavaScript.

<html>
<head>
  <script src="http://code.jquery.com/jquery.js" runat="both"></script>
  <script>
    jQuery(function($){
      $("form").submit(function(){
        save( $("textarea").val() );
        return false;
      });
    });
  </script>
  <script runat="server">
    function save( text ){
      Jaxer.File.write("tmp.txt", text);
    }
    save.proxy = true;
   
    function load(){
      $("textarea").val(
        Jaxer.File.exists("tmp.txt") ? Jaxer.File.read("tmp.txt") : "");
    }
  </script>
</head>
<body onserverload="load()">
  <form action="" method="post">
    <textarea></textarea>
    <input type="submit"/>
  </form>
</body>
</html>

There's a bunch of key points here that we need to take a look at in order to understand what's going on here, however it's most important to note that this application looks just like a normal HTML/JavaScript/DOM web app - there are no significant differences in syntax or style. Let's dig in and see what all there is at play here.

  • runat="both" and runat="server" - These script blocks are just like normal script blocks, but with an important exception: They both are capable of running on the server, rather than on the client. It's important to remember that since a Jaxer server is just like a headless Firefox, thus it's able to handle the same JavaScript that Firefox can. In this case that's both the whole jQuery library and a couple of helper functions. The runat="both" declaration, additionally, states that the script block should be executed on both the client and the server (in this demo we're using jQuery in both places).
  • Jaxer.File - These set of methods are part of the Jaxer API. It's important to note that these functions can only be run on the server-side, thus they should only be called in a server-capable script block. The methods do what you would expect them to: They allow you to do simple interactions with text files.
  • save.proxy = true; - The save() function must exist on the server-side (since it contains calls to server-side functionality) however we want to be able to call it from the client-side whenever the user hits the submit button to save their textarea changes. We can do this by making it a proxy function (adding an extra proxy property to the function). This actually creates a stub function on the client-side, to allow the code to continue working as it would expect, while obscuring the actual functionality behind an Ajax request. It's all completely seamless and works as you would expect it to, which is impressive. You can also make functions proxy functions by using a runat="proxy" on a script block.
  • onserverload="load()" - This attribute gives a simple mechanism for running a piece of server-side functionality on DOM ready. In this case we're loading the contents of the saved text file and injecting it into the textarea, using jQuery.

There's also one thing that I want to mention: I built the above mini app after only a cursory glance through the examples and it worked 100% perfectly out of the box, with no errors whatsoever. This is really hard to do and even more so with the first release of a project - I'm quite impressed. Even taking nothing else into account it's pretty obvious that Jaxer is easily the most exciting piece of JavaScript technology to arrive in a long time.

Disclaimer: I'm a proud member of Aptana's advisory board. I've been greatly impressed with their work and I'm glad they asked me to join them.

Tags: aptana, server, javascript, mozilla

Instant JavaScript Apps

This past summer I swung by Y Combinator a couple times to scope out the new startups. (Fun fact! I was in Y Combinator during the Summer of 2006.) Out of all the startups there one really caught my eye: AppJet.

They were setting out to build a quick-and-easy way to construct web applications using, their language of choice, JavaScript. They were doing all of this using Rhino, giving each application its own instance to play with. I met up with them to discuss things, how apps were going to be built, what standard libraries to provide; they were on a good track, and by the look of today's launch, they were quite successful.

Just to list some really-cool things that they've done:

Just to give you a taste, here's the full source code to a "shoutbox" application. (Remember, this is server-side/client-side mixed!)

import("storage");

var historySize = 20;

if (! storage.msgs) {
    storage.msgs = new StorableObject();
    storage.start = 0; // first msg
    storage.end = 0; // index after last msg
}

if (request.isPost) {
    var newText = request.params.newText;
    storage.msgs[storage.end++] = request.params.newText;
    while (storage.end - storage.start > historySize) {
        delete storage.msgs[storage.start++];
    }
    response.redirect("/");
} else {
    print(FORM({id:"shoutform",action:"/", method:"post"},
          INPUT({type:"text", name:"newText", size:40}),
          INPUT({type:"submit", value:"shout!"})));
    var messageDiv = DIV({id:"msgs"});
    for(var i=storage.end-1; i >= storage.start; i--) {
        messageDiv.push(P(storage.msgs[i]));
    }
    print(messageDiv);
}

I'm very impressed: Congrats David, Aaron, and J.D.!

Tags: javascript, server, applications

Brief Outage

Sorry for the brief outage today - apparently a couple of my domains have been getting a huge amount of spam lately (in the multi-gigabyte range) which caused the disk space to run out in this particular partition. If you notice any other weird SQL errors, or such, be sure to let me know.

Tags: site, server

Word to the Wise

Word to the Wise: If you run a dedicated web server for multiple people and web sites - make sure none of the sudo-capable accounts use a dictionary-based password. Ever. With that in mind, the past few days have been a complete mess. Luckily, all the data and files were saved from my various web sites (this one included) - and no data was lost or stolen. I forgot to copy a couple .htaccess files during the transfer, so I'm working on rebuilding them from memory. Regardless, everything should be 'ok' with this web site now, all the bugs seem to have been cleared away. I still have a couple web sites that need to come up (ideashrub, and some new, unmentioned, projects included) due to the fact that they need some additional TLC. Sorry for all of the mess.

To make up for it, I'm planning on releasing a project every day for the next couple days. I've been playing with some new technologies and I really want the chance to show all my work off.

Tags: server, blogs, hacking

Current Projects

jQuery JavaScript Library

jQuery

Comprehensive DOM, Event, Animation, and Ajax JavaScript Library.

Recent Projects

Pro JavaScript Techniques

JavaScript Book

The best techniques for professional JavaScript. Published by Apress.


Hosting provided by the cool dudes at Engine Yard.