Fork me on GitHub

Updates from March, 2012 Toggle Comment Threads | Keyboard Shortcuts

  • britg 8:58 am on March 15, 2012 Permalink | Log in to leave a Comment
    Tags: , spdy,   

    SPDY and Its Relation to WebSockets 

    When SPDY was first announced I didn’t pay too much attention as history has shown it takes years before these things become widely adopted, if ever. Recently though, Twitter launched support for the protocol and I noticed (via this Chrome plugin) that quite a few of the sites I visit on a regular basis (mostly Google properties) are actually using SPDY in production.

    Interesting. I guess it’s time to pay attention.

    But, WebSockets!

    My first question, without knowing too much about SPDY, was what its relation was to WebSockets — are they two competing implementations solving the same problem? The short of it is: No, they are complimentary and will coexist. Here’s my best attempt to relate the two:

    SPDY is an augmentation to HTTP with the goal of making synchronous HTTP requests faster.

    WebSockets is an alternative to HTTP with the goal of facilitating real time communication.

    The big point here being that SPDY shouldn’t require too much application-level refactoring, whereas supporting WebSockets means building an application specifically for bi-directional communication.

    Push

    A word often bandied about is push and it has two different meanings with these technologies.

    SPDY Push is a technique where more than just the requested resource is sent down the pipe to a browser, but within the context of a single request. Example: on a given HTML page there’s a good assumption that the corresponding .js and .css and a few images will be requested. SPDY can send all of these in a single request, eliminating quite a bit of RTT (round trip time).

    WebSockets Push facilitates asynchronous communication between the server and browser. The server receives new data from another source and rather than waiting for the browser to request the new data, it is simply pushed through an already-open connection.

    Complimentary

    The two protocols are actually complimentary. WebSockets makes its initial handshake with servers over HTTP to discover if the ws:// protocol is supported, and one of SPDY’s primary methods of optimization is compressing and caching HTTP request headers.

    From the SPDY Whitepaper

    Header compression resulted in an ~88% reduction in the size of request headers and an ~85% reduction in the size of response headers… We found a reduction of 45 – 1142 ms in page load time simply due to header compression.

    So, in an ideal future the RESTful request-based web is driven by SPDY, and all of the real-time communication and “app-ifying” is handled via WebSockets. Two peas in a pod!

     
    • Curt 7:40 pm on May 2, 2012 Permalink

      Hi, nice write up. You have helped me understand the difference between these 2 seemingly similar techs. I think that SPDY should find a new term besides Push as it adds confusion and does not describe the act of sending multiple resources simultaneously.

    • Bill 9:24 am on May 15, 2012 Permalink

      I concur, excellent write-up. Note that you meant “complementary”.

  • britg 11:01 am on January 15, 2012 Permalink | Log in to leave a Comment
    Tags: css3, , ,   

    Forging Forgecraft: Integrating CSS3 Transitions with Javascript 

    Forgecraft is a game currently in development using Ruby on Rails, Backbone.js, and all sorts of HTML5 buzzwords. Read an introduction here, and play the demo here.

    With Forgecraft, and any game really, there are usually quite a few animations running concurrently. I found these moments to be choppy, unresponsive and frustrating when they were implemented in javascript (especially on lower CPU environments like the iPad) and needed another solution. CSS3 transitions were an obvious choice to check out, as they’ve been shown to be a great way to add a little pizzazz to a modern web app and can be executed natively (and even GPU accelerated).

    But, can they provide the technical underpinnings for an interactive gamely element? To be effective in this context, they’d have to be:

    • responsive, consistent and reliable
    • noticeably smoother than their javascript counterparts
    • simple to integrate with scripting

    Regarding the first 2 points, CSS3 transitions’ effectiveness will really depend on your particular use-case. With Forgecraft they were definitely response, reliable, and smoother than javascript and I decided early on to use them in lieu of javascript wherever I could. But, I won’t go into the benchmarks and A/B comparisons in this article… perhaps later. Let’s just skip straight to the useful part:

    Product Intergortion obscure 30 Rock reference →

    Integrating CSS3 transitions with the game’s scripting is pretty straight forward:

    • Define transitions in CSS on your master element
    • Define classes with resulting properties changed
    • Trigger a class change using javascript
    • Listen for the transition-end event with javascript

    Of course, there are a few pitfalls with each of these steps that I’ll go into here. Let’s take an example from Forgecraft: the Bonus Strike event. Randomly while forging the player will see a bar pop-up like this:

    The bar moves from left-to-right and the player’s goal is to click the icon when the moving bar is directly under the target (large white) bar. The moving bar is animated with CSS3 transitions.

    Defining the CSS:

    We have a bar that needs an initial negative offset (the start position) that transitions to its final position. Simple enough: we define the base CSS on the #bar element and give it two classes (.new and .activated) defining each of its states. We also define the transition between the two states:


    position: relative;

    background-color: rgba(153, 153, 153, 0.3);
    border-right: solid 5px white;

    -moz-transition-property: left;
    -webkit-transition-property: left;
    -o-transition-property: left;
    transition-property: left;
    -moz-transition-duration: 1.5s;
    -webkit-transition-duration: 1.5s;
    -o-transition-duration: 1.5s;
    transition-duration: 1.5s;

    }

    #bar.new {
    left: 0px;
    }

    #bar.activated {
    left: 600px;
    }

    One pitfall you may run into: for the animations to work in Firefox, you have to explicitly define the initial state for whatever property you are transitioning. In this example we are transitioning the left property of the #bar element. You normally wouldn’t define left: 0; — that’s the default! But Firefox requires this to trigger the transition when that property changes.

    Triggering the Animation in Javascript

    Using jQuery, we simply apply the classes that we defined in the CSS when we want to trigger the transition.


    Listening for the transition-end event

    CSS3 Transitions would be useless if we couldn’t get their context from within our scripting. Luckily, a series of events are fired in javascript while the transitions are running, just like you’d expect in a javascript-based animation. The primary event we care about is when the transition ends as you’ll most likely want to trigger callbacks.

    Unfortunately, each browser vendor has decided to name these events differently… typical huh. Modernizr to the rescue! (If you’re not using Modernizr, you should be. But that’s another blog post altogether).

    There’s a hidden gem in the comments in the source code of Modernizr that explains how to use its .prefixed() API to make a simple wrapper around the browser-specific transition event names. Here’s how I implemented it for the transition-end event. Feel free to use this wherever you need it:


    var transEndEventNames = {
    ‘WebkitTransition’ : ‘webkitTransitionEnd’,
    ‘MozTransition’ : ‘transitionend’,
    ‘OTransition’ : ‘oTransitionEnd’,
    ‘msTransition’ : ‘msTransitionEnd’, // maybe?
    ‘transition’ : ‘transitionEnd’
    },

    CSS3_TRANSITION_END = transEndEventNames[ Modernizr.prefixed('transition') ];

    Bam, now we can use one simple event binding to handle all browsers:


    Stopping a Transition Early

    When the player hits the hammer-and-anvil icon during the Bonus Strike event, I needed to stop the animation early. The easiest way I found to do this, was to just set the animating property to its current value. The transition delta becomes 0, so the animation stops:


    Transition: End

    You may find that integrating CSS3 Transitions into your game makes your interactions smoother and more responsive, and with a simple API for scripting against transition events, developing against them should look and feel a lot like working in pure javascript.


    More Forging Forgecraft:

     
  • britg 12:07 pm on January 10, 2010 Permalink | Log in to leave a Comment
    Tags: , , webgl,   

    Quick Look: WebGL and Web Sockets 

    The internet is still a very young ecosystem of immature techn… Woah, the BS meter pegged there for a second. Forget the pontification, let me just spit out the two technologies that get me excited about billing myself as a Web Developer.

    WebGL

    This is a new spec that’s being developed by the Khronos Group (the group behind OpenGL) to expose OpenGL to browsers through the canvas element.

    Why is it exciting? Three words: Javascript. Hardware. Acceleration. Damn, I need three more: In. The. Browser.

    The concepts should speak for themselves, but if you still need some convincing follow the steps below and be sure to take a look at your CPU usage while running these demos. (Hint: CPU usage will be very low because you’re riding your GPU).

    • Grab the latest nighly of Chromium here if you are not already running it.
    • Start Chromium via the command line:
      • Windows: chrome.exe --no-sandbox --enable-webgl
      • OSX: Chromium.app/Contents/MacOS/Chromium --no-sandbox --enable-webgl
      • Linux: ./chrome --no-sandbox --enable-webgl
    • Follow this link to some examples of WebGL in action.

    Again, check your CPU usage while running the demos. It should be very low (if you have a GPU) as the demos should be hardware accelerated.

    Web Sockets

    Comet? Long-Polling? Forever Frame? In two years we will all be sitting around a trash barrel fire laughing about the days of yore when we had to use such hacks.

    Why are we huddled around a trash barrel fire? Because it’s post-apocolyptic New Zealand, the last bastion of humanity. Anyways, that’s another “In This Decade” blog post…

    From websockets.org:

    [The Web Socket Interface] defines a full-duplex communications channel that operates over a single socket and is exposed via a JavaScript interface in compliant browsers

    Here’s the spec in case you want to read it… haha, me neither.

    Again, the concept here should speak for itself. Two-way communication with web servers in an easy-to-use interface.

    
    var websock = new WebSocket("ws://www.websocket.org");
    
    websock.onopen = function(evt) {
      console.log(evt)
      websock.send("Hello Web Socket!");
    };
    websock.onmessage = function(evt) {
      console.log(evt)
    };
    websock.onclose = function(evt) {
      console.log(evt)
    };
    websock.close();
    

    Fortunately, there are already many projects implementing the web sockets protocol. To name a few,

    One thing to note is that the web socket protocol will adhere to the cross-domain security restriction that XHR has. The good news is it will ship with support for server-side origin discretion using the same Origin headers in CORS.

    It’s all about the gaming, stupid

    I’m going to predict that in 2 years, we will see current A quality games developed in-browser ontop of these two technologies. Don’t get me wrong, AAA quality console and PC titles won’t be disrupted like the music and print industries any time soon. But, the “casual” label on browser games will go away.

    This is what has me really excited about being a web developer in this decade. Parity with desktop development is inching closer, and all ontop of open technologies.

    No plugins. No corporate owner.

    Win. Win.

     
    • peterlubbers 12:44 pm on January 11, 2010 Permalink

      Nice post! I'd like to add Kaazing WebSocket Gateway to the list of implementations. It's a production-ready WebSocket Gateway. The best part? It has emulation for all the older browsers (Anything other than Chrome right now), so you can already use WebSocket APIs today.

    • Pl4n3 3:12 pm on March 12, 2010 Permalink

      Nice posting! Games using WebGL and WebSockets is a nice perspective. I made a RTS-game demo using WebGL http://pl4n3.blogspot.com/2010/03/towards-webrt…, I also plan to integrate websockets for the multiplayer-part.

    • britg 3:38 pm on March 12, 2010 Permalink

      Hey Pl4n3 — awesome that you're working on an RTS in WebGL! Your demo throws an error in Webkit nightlies, though — “Error: 0:3: 'uniform' : cannot initialize this type of qualifier” (with wegGL enabled)

      Which browser are you recommending for the demo?

    • Pl4n3 4:09 pm on March 12, 2010 Permalink

      Thanks, also for the RT :) The RTS currently runs here with Firefox 3.7 (Minefield) nightly. Yesterdey it also worked with Chrome, but today WebGL could not initiate there, strange..

    • evilhackerdude 8:07 pm on March 16, 2010 Permalink

      Hey, I tried the RTS demo with the latest Minefield nightly (3.7pre4 I thin), yet I got exactly same error as Brit.

    • Pl4n3 3:34 am on March 17, 2010 Permalink

      Hi, i just updated Minfield to the latest version here (3.7a4pre), and the demo runs without problems. Currently cannot reproduce the error :/ Hopefully later, as WebGL gets more stable, this might resolve itself.

    • Lindsay Stanley Kay 5:08 am on July 2, 2010 Permalink

      Aha great post this, cheers, helps me get started here.

      Yes it seems that the WebGL framework hackers, having got things drawing, are rightfully turning their attention now to the backend. I just added Sockets to SceneJS as well: http://scenejs.wikispaces.com/SceneJS.Socket – early days – comments appreciated!

      Pl4n3 – whoah – looking forward to seeing how you implement the game logic/protocol etc! PS Your demo works good for me in Chromium build #51510

    • lingerie 12:09 am on August 20, 2010 Permalink

      It's so tough to encounter right information on the blog. I realy loved reading this post. It has strengthen my faith more. You all do such a great job at such Concepts… can't tell you how much I, for one appreciate all you do!

    • Arne Wieding 7:12 am on November 23, 2010 Permalink

      Nice post, however i think you are being very optimistic here. I think this will rather take 4-5 years instead of 2. Especially since your post in now roughly a year old and not much has changed, the next browser generation still hasnt arrived in a stable form.

      Furthermore id like to add that most modern games use UDP while WebSockets use TCP/IP which is not well suited for games. You might do some simple games with that, but any real time multiplayer games dont work that well.

      Still interesting tech, but it will take some more years to mature.

    • modern home design 10:06 am on February 13, 2011 Permalink

      It looks like webgl is more promising…

    • bouncy castles for sale 1:06 am on February 19, 2011 Permalink

      Great!This is awesome!Thank you!

    • web design london 8:36 pm on August 11, 2011 Permalink

      Nice posting! Games using WebGL and WebSockets is a nice perspective.

  • britg 10:46 am on December 29, 2009 Permalink | Log in to leave a Comment
    Tags: , , , , sinatra   

    Cross Origin Resource Sharing with Sinatra 

    It’s no lie that I think highly of the potential of Cross Origin Resource Sharing. One of the great things about it is that it doesn’t take much re-wiring of existing server (or client-side) apps to start working cross domain.

    Enabling your server app is as simple as including a few extra headers when you detect a cross origin request. How do you know it’s a cross origin request? You’ll see the Origin: header — all CORS requests will have it. From there, response headers depend on the specifics of the request, but I won’t go over those here — check out the Mozilla Developer Center treatment for in-depth information.

    I’ve been working with Sinatra a lot lately, so I put together an extension for Sinatra that makes enabling Cross Origin requests even easier.

    sudo gem install sinatra-cross_origin

    There are two ways to use the extension: globally or per-route.

    Global

    For when you want to share all your endpoints cross-domain.

    
    require 'sinatra/base'
    require 'sinatra/cross_origin'
    
    class MyApp < Sinatra::Base
      register Sinatra::CrossOrigin
    
      enable cross_origin
    
      get '/' do
        "This is available to cross domain javascript requests automatically"
      end
    end
    

    Per Route

    For when you want to share only some of your routes cross-domain.

    
    require 'sinatra/base'
    require 'sinatra/cross_origin'
    
    class MyApp < Sinatra::Base
      register Sinatra::CrossOrigin
    
      get '/' do
        cross_origin
        "This is available to cross domain javascript requests"
      end
    end
    

    Configuration

    You can mix and match app-wide config and request specific config.

    
    require 'sinatra/base'
    require 'sinatra/cross_origin'
    
    class MyApp < Sinatra::Base
      register Sinatra::CrossOrigin
    
      configure do
        # Comma separate list of remote hosts that are allowed.
        # :any will allow any host
        set :allow_origin, :any
    
        # HTTP methods allowed
        set :allow_methods, [:get, :post]
    
        # Allow cookies to be sent with the requests
        set :allow_credentials, true
      end
    
      get '/' do
        # Only available to GET requests originating from
        # http://example.com.  No cookies allowed.
        cross_origin :allow_origin => 'http://example.com',
          :allow_methods => [:get],
          :allow_credentials => false
        "This is available to cross domain javascripts"
      end
    end
    

    Grab the source at Github: britg/sinatra-cross_origin.

     
    • escort services 9:19 am on March 1, 2011 Permalink

      Cross-origin resource sharing Sending messages is not the only solution for sharing information between different websites. The cross-origin resource sharing API loosens the controls over AJAX calls to anywhere but the home domain. …

    • Chris Castle 4:52 am on July 4, 2011 Permalink

      Hey Brit-  Thanks for putting this together.  I’m trying to make an HTTPS cross-domain request with Basic Auth.  I’m using Sinatra (obviously) on the server and jquery on the client.  I’m getting a 401 Unauthorized response from the server.  In looking at the Request headers I don’t see the browser sending the ‘Authorization’ header.  Here are the request and response headers.  Any idea what’s wrong?  If I hit the Request URL by itself in a browser, the auth box pops up, I enter my credentials, and everything works great — but not when it’s requested via javascript…

      Request URL:https://my.site.com/ec2/describe?env=dev&instanceId=i-b285d4dfRequest Method:GETStatus Code:401 UnauthorizedRequest HeadersAccept:*/*Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3Accept-Encoding:gzip,deflate,sdchAccept-Language:en-US,en;q=0.8Connection:keep-aliveHost:my.site.comOrigin:http://localhost:4567Referer:http://localhost:4567/index.htmlUser-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.41 Safari/535.1Query String Parametersenv:devinstanceId:i-b285d4dfResponse HeadersAccess-Control-Allow-Credentials:trueAccess-Control-Allow-Headers:AuthorizationAccess-Control-Allow-Methods:GET, POST, UPDATE, DELETE, OPTIONS, HEADAccess-Control-Allow-Origin:http://localhost:4567Access-Control-Max-Age:1728000Connection:keep-aliveContent-Length:15Content-Type:text/html;charset=utf-8Server:thin 1.2.11 codename Bat-Shit CrazyWWW-Authenticate:Basic realm=”Restricted Area”

  • britg 12:11 am on December 17, 2009 Permalink | Log in to leave a Comment
    Tags: , ,   

    Scriptstack – Organize and Share Javascripts 

    scriptstackI’ve been hacking on a small project in my free time that I uploaded today: scriptstack.

    What is scriptstack?

    Well, if you’re like me you probably have 4 or 5 javascript files you include in just about every new project or site your start. jQuery. Tooltips. Lightbox. qTip. Or, you just put together a nice portfolio site for a client and you want to save that specific set of javascript plugins for the next time you do something similar.

    Scriptstack aims to be an easy and social way to organize your “stacks” of scripts. You can:

    • Upload scripts.
    • Click and drag them into the order they should be loaded in the browser.
    • Tag them with a few keywords to make them indexable for future search.
    • Download the concatenated stack in minified or raw format.

    That’s about it for now, haha. Release early, release often, right? I should note that there’s no permissions on the stacks. If you create one, it’s editable by anyone right now. I plan to add User accounts and ownership soon.

    Warning: the site probably only works in Firefox.

    Under the hood

    I took this opportunity to expand my horizons as far as the technology under the hood. I’ll go in-depth on these as I continue to develop, but a quick rundown of the tech stack (pun intended but probably shouldn’t be):

    I also open sourced all the code that runs the site here incase you are interested in what poorly written Ruby looks like.

    If you happen to check it out, let me know what you think! And as I said, I will expand on different parts of it here in the near future, so stay tuned.

     
  • britg 11:17 pm on December 11, 2009 Permalink | Log in to leave a Comment
    Tags: ajax upload, , , jsonview   

    Ajax Uploading Plus JSON Response Plus JSONView = Disaster 

    So, I’ve spend the last few hours debugging what seemed to be a tear in the fabric of the universe. I’m working this excellent javascript library, AjaxUpload, that, as the name implies, creates a no-pageload form upload. It’s easy to implement and makes an upload infinitely more usable in my opinion; definitely check it out.

    The upload works by pointing the target attribute of a multipart form at a hidden iframe. When the iframe updates with the results of the upload, an event listener reports the response to the parent page, and voila — you have an upload without a page refresh.

    The only problem with this iframe approach is that your response is being fully rendered by the browser instead of passed in the response body of an XMLHttpRequest like most ajax interactions. Combine this with a server-side upload script that returns JSON and here’s where the fun starts.

    If you’re using the JSONView Firefox plugin (and why the hell aren’t you!?) the JSON gets rendered with some wrapper html and styling to create an interactive and human readable version of the JSON.

    See the problem here? What gets reported to your upload-complete event listener isn’t the original JSON, but the HTML-wrapped JSON. This can lead to what can only be described as multiple hours of FAIL in which you try and figure out why your JSON response can’t be parsed and used in your javascript.

     
    • DVD Duplicator 12:27 am on October 27, 2010 Permalink

      Thanks for sharing your experience.

    • philbocq 10:53 am on December 3, 2011 Permalink

      I encountered the same problem, however you can change the header response from application/json to text/html so jsonview doesn’t detect the returned page as json and ajaxUpload works

  • britg 12:22 pm on December 6, 2009 Permalink | Log in to leave a Comment
    Tags: , javascripts, , tooltips   

    qTip – jQuery Tooltip Plugin with Excellent Docs 

    qTip - jQuery Tooltips

    qTip - jQuery Tooltips

    The bar has been set on jQuery plugins by this simple yet very robust project: qTip.

    What is it? An easy way to create fancy tooltips that has (optional) customization options for just about anything you want to do. I had been using a pretty old and bland library before, so I was excited to stumble on this one.

    Example: a tooltip positioned at the bottom left of a selector, with a green color scheme and a little tip pointing to the selector.

        $('#myselector').qtip({
            content: 'Eat my tooltip, sucker!',
            position: {
                corner: {
                    target: "bottomLeft",
                    tooltip: "topLeft"
                },
                adjust: {
                    x: 10,
                    y: 10
                }
            },
            style: {
                name: "green",
                tip: "topLeft"
            }
        });
    

    Perhaps the best part of this plugin is the documentation. Just check them out and tell me that’s not the most well-documented library you’ve ever seen.

     
  • britg 8:10 am on December 2, 2009 Permalink | Log in to leave a Comment
    Tags: , cross-domain, , , , XHR   

    Cross Origin Resource Sharing – AKA The Holy Grail 

    The other day I was chatting with a guy about the overly restrictive cross-domain request policy and how silly it is given the pervasiveness of cross-domain apps on the web today. Most devs get around this restriction with hacks like jsonp or nested iframes anyways. I told him that it’s high time we move past this archaic security measure and take web apps to the next level!

    He just said, “Uh… do you want to upgrade your coffee to a venti for only 35 cents more?” Always the salesman that guy…

    Cross Origin Resource Sharing

    Recently I stumbled across this article on the excellent Mozilla Hacks blog. Cross Origin Resource Sharing (CORS). Sweet! Finally a true implementation of cross-site XMLHttpRequests.

    The CORS standard works by adding new HTTP headers that allow servers to serve resources to permitted origin domains.

    They’re getting everything right with this one:

    • it’s completely opt-in server-side, so browsers can implement CORS without opening up a bunch of security holes,
    • it uses the existing XMLHttpRequest object so current code can easily start working cross-domain,
    • and it’s totally transparent to the client-side developer — validation, pre-flighting, and access control is all handled within the XMLHttpRequest object without any additional code!

    Apparently it’s been in the works at the W3C for a couple of years (formerly known as ‘Access Control‘). But only the most recent versions of Firefox and webkit based browsers are starting to support it. Of course Microsoft, in their infinite wisdom, decided it would be best to implement their own spec, XDomainRequest. Some things never change…

    The Holy Grail

    Not the knights who say Ni

    Not the knights who say Ni

    Is this a big deal? I’m going to go out on a limb here and say this is the holy grail of web development!

    Why? For one, there isn’t a good, non flash-based way to implement cross-domain long-polling/comet. If there’s one thing that’s going to define the next generation of the web, it’s real-time apps. CORS enables efficient real-time “mashups” (hate that term) that don’t rely on iframe hacks or flash.

    Psh… cross-domain, real-time? Nothing more than a niche application, right? Not so fast.

    The web will soon (if not already) start its industrial revolution. A “building up” versus the “building out” if you will. New web development will progressively become based around existing sites, rather than the creation of new sites. A true cross-domain solution is vitally important to this.

    No, no, I’m not saying that people will stop creating new sites — that will always happen. I’m saying startups will turn more and more to building apps targeted at sites users are already invested in instead of trying to get them to some new property.

    Examples:

    • The Disqus comment app on this blog.
    • The Meebo Bar
    • Those little ‘Feedback’ widgets you see all over sites now.

    A new ecosystem is emerging: apps built with web technologies that run on other sites. But they’re mostly iframe based with all the restrictions that iframes have (no access to the DOM, slow, etc). With CORS, developers can almost seemlessly develop apps cross-domain with all the power of same-domain scripting, making it the most important development to come along since the XMLHttpRequest!

    In future posts I’ll delve into this “industrial revolution” of the web, but for now… back to that grail.

     
  • britg 8:00 am on July 1, 2009 Permalink | Log in to leave a Comment
    Tags: comet, , , , long-polling, node,   

    Server Side Javascript Continued – Node.js (plus example) 

    Update: Node’s APIs have change quite a bit since this post was made. Check out the latest stuff at nodejs.org!

    In my previous post on server-side javascript (SSJ) I took a quick look at Jack, a project that aims to implement the Rack/WSGI pattern for javascript. I still think this approach is great as it opens the door for more traditional Rails/Django-esque frameworks for SSJ.

    But, lets face it, the next gen web is all about real-time interactivity, and current popular environments and servers just aren’t ideal for that. It’s not their fault, up until recently we only cared about getting that request handled and out the door as quickly as possible with nothing shared between requests. Unfortunately, it’s no longer just about number of requests/sec — we now need high concurrency, long-lasting connections, and shared persistence over these connections.

    Node.js

    Enter node.js – a high performance javascript project built ontop of Google’s V8 runtime. From the author’s description:

    Node’s goal is to provide an easy way to build scalable network programs. … Each connection is only a small heap allocation. This is in contrast to today’s more common model where OS threads are employed for concurrency.

    Nice, but does this pan out in implementation? After spending a few days with Node, I truly believe that this will be the go-to project for the future of the real-time web.

    A Simple Game Lobby

    Let’s take a look at a simple example I put together. The following is a very basic game lobby that is based on a more complex project I’m working on with node. (You can checkout this script from github as well).

    The script accepts new players through a url like /join?player=joebob. Then, the client can long-poll the URL /wait and receive a notification in real-time when new players join!

    First, lets define a couple of Arrays that will hold our persistence in-memory.

    // our in-memory list of player
    var players = [];
    
    // our in-memory list of players waiting
    var waiting = [];

    Next, lets define a set of URLs our server will respond to. Notice that the /wait response does not take place immediately. Instead, the response is captured in a callback function that is held in-memory until it is called. These callbacks are called whenever a new player hits the /join URL.

    // define a set of paths that respond to requests
    var paths = {
    
      /**
       * Requests to /join add players to our
       * player list, and fire off a notification
       * to all our waiting players
       **/
      "/join": function(req, res) {
    
        // extract the player from the request
        var newPlayer = req.uri.params.player;
    
        // respond to this request with a list of players
        // already in the lobby
        server.respond(200, players);
    
        // add this player to list of players
        players.push(newPlayer);
    
        // notify all of our waiting players that
        // a new player has joined
        while(waiting.length > 0) {
          waiting.shift().callback.apply(this, [newPlayer]);
        }
      },
    
      /**
       * Requests to /wait holds the connection
       * open until another player joins
       **/
      "/wait": function(req, res) {
    
        // define our waiting player and the notification
        // callback to trigger when another player joins
        var waitingPlayer = {
          "player": req.uri.params.player,
          "callback": function(newPlayer) {
             server.respond(200, newPlayer);
           }
        };
    
        waiting.push(waitingPlayer);
      }
    };

    Finally, we define our server. We tell the server to map requests to the paths we defined above, and to listen on port 8000.

    // Define a new HTTP Server
    var server = node.http.createServer(function (req, res) {
    
      // tell our server to look at the paths definition above
      // for a responder to the request
      paths[req.uri.path].apply(this, [req, res]);
    
      // respond to a request
      function respond(status, obj) {
        var body = JSON.stringify(obj);
        res.sendHeader(status, [ ["Content-Type", "text/json"]
                             , ["Content-Length", body.length]
                             ]);
        res.sendBody(body);
        res.finish();
      }
    });
    server.listen(8000);
    puts("The game lobby has started!");

    To run the script, first download and build node, and then download this script from my repo. Execute the script with:

    > node gamelobby.js

     
    • Hagen 2:11 pm on July 1, 2009 Permalink

      Nice article!

      But a very bad idea to show HTTP example code completely ignoring request verbs. People will copy that :-/ And don't make people join on GET, use PUT to join, DELETE to unjoin.

    • britg 2:34 pm on July 1, 2009 Permalink

      True, I plan to make some updates, the first of which is to use POST on the /join URL and enforce it. Also, I will implement a reaper process to clear stale joins.

    • TJ Holowaychuk 5:28 pm on July 1, 2009 Permalink

      check out http://github.com/visionmedia/express/tree/master
      might like ;) , I just started it but contribution would be great, building a framework on node.js is sexxxxy

    • britg 5:47 pm on July 1, 2009 Permalink

      Very cool, will watch its progress on github :) I like the Sinatra-esque lightweight approach.

    • john 7:22 pm on July 20, 2009 Permalink

      Hi! This example does not seem to be working with 2009.06.30 node-0.1.0.tar.gz

      When I call /join?player=john then

      The game lobby has started!
      example.js:28: TypeError: Object [object Object] has no method 'respond'
      server.respond(200, players);
      ^

      But THANKS for putting this blog post out there. Really exciting!
      Best,
      John

    • britg 8:39 pm on July 20, 2009 Permalink

      Hey John – from your console output, it looks like you are making requests to the wrong script.

      “example.js:28 …”

      The name of the script, if you used the same copy from the github repo, should be 'gamelobby.js'

      Let me know if that helps!

    • john 10:58 pm on July 20, 2009 Permalink

      Sweet! That works :)

      Thanks britg, very fun stuff! I'm planning to build a small comet server using node.js

      Best,
      John

    • gracybonsu 2:13 am on May 3, 2010 Permalink

      Thanks for giving me this useful information
      http://www.shakespearefinance.co.uk/

    • Ron 12:00 pm on May 21, 2010 Permalink

      Here is a nice screencast: http://www.videorolls.com/watch/node-js-screencast . I believe it may be of some help.

    • Vlad_savitsky 8:49 am on October 26, 2010 Permalink

      I have installed node 0.3.0 and try your script. And I have got an errror:
      —————————
      node.js:50
      throw e; // process.nextTick error, or 'error' event on first tick
      ^
      ReferenceError: node is not defined
      at Object.<anonymous> (/home/vlad/Документы/Скрипты/node.js/Examples/Game Lobby/britg-node-simple-lobby-a9d459f/gamelobby.js:14:1)
      at Module._compile (node.js:348:23)
      at Object..js (node.js:356:12)
      at Module.load (node.js:279:25)
      at Array.<anonymous> (node.js:370:24)
      at EventEmitter._tickCallback (node.js:42:22)
      at node.js:634:9
      —————————
      Where can be the problem? I don't know node.js well to handle this myself. Please help me to fix it.</anonymous></anonymous>

    • Vlad Savitsky 9:10 am on October 26, 2010 Permalink

      0.3.0 is unstabe version. I have installed 0.2.4 (stable) and have got this error:
      ———————————————
      node.js:63
      throw e;
      ^
      ReferenceError: node is not defined
      at Object.<anonymous> (/home/vlad/Документы/Скрипты/node.js/Examples/Game Lobby/britg-node-simple-lobby-a9d459f/gamelobby.js:14:1)
      at Module._compile (node.js:462:23)
      at Module._loadScriptSync (node.js:469:10)
      at Module.loadSync (node.js:338:12)
      at Object.runMain (node.js:522:24)
      at Array.<anonymous> (node.js:756:12)
      at EventEmitter._tickCallback (node.js:55:22)
      at node.js:772:9</anonymous></anonymous>

    • pdfdownload ebook 3:12 pm on February 17, 2011 Permalink

      Nice, but does this pan out in implementation? After spending a few days with Node, I truly believe that this will be the go-to project for the future of the real-time web.

    • Cam 6:20 am on April 13, 2011 Permalink

      this is not working anymore, I use node version 0.5 pre and I have the same error as Vlad_savitsky. Thanks for the contribution anyway. Cheers

  • britg 7:00 am on June 8, 2009 Permalink | Log in to leave a Comment
    Tags: , jack, javscript, , narwhal,   

    The Brave New World of Server-Side Javascript 

    Not the B Team

    Not the B Team

    Every once in a while I hear whispers of server-side javascript and I get just as excited as the next person. But, I’ll admit that until recently a phrase like “Javascript on Rails” was on the same level as a phrase like “McGyver vs. The A Team – The Movie.” Fictonal. But awesome in theory.

    (Don’t worry, they eventually join forces in the sequel)

    But what about Jaxer?

    My limited experience with server-side javascript (SSJ) has been through Jaxer, from Aptana.  It touts some cool functionality, like loading the DOM server-side and built-in database drivers for MySQL, with the former allowing for DOM manipulation and integration with libraries like jQuery.

    The extremely original Gear logo

    Ubiquitous "Gear" Logo

    But, in its attempts to blur the lines between client and server execution, Jaxer has made sacrifices in its extensibility. It is meant to be plugged into another system. For instance, I don’t know of an easy way to expose data through a RESTful JSON/XML API (like so many sites are doing nowadays) using Jaxer alone.

    What I’m really looking for in SSJ is something akin to the ecosystem surrounding languages like Ruby and Python.  That’s why I was pleasantly surprised to stumble accross a few projects that aim to do just that.

    Narwhal – Javascript Standard Library and Interactive Console

    The foundation of any good ecosystem is a standard library.  Enter Narwhal, “a flexible javascript standard library.”

    There are a lot of things to like about this project, but the primary benefit is its attempts to play nice with multiple javascript runtimes like Rhino and V8cgi.  Also, this project is embracing Mozilla’s ServerJS standard which I think is important for its longevity and interoperability.

    Setup is a breeze, you can simply clone the project from github:

    git clone git://github.com/tlrobinson/narwhal.git

    Once you add narwhal/bin to your $PATH, you can use the convenient symlink js to enter an interactive javascript console similar to irb or python.

    Jack – Javascript’s “Rack”

    Interestingly enough, Narwhal came into existence as it’s author, Tom Robinson, was working on Jack.

    JSGI is a webserver interface for JavaScript inspired by Ruby’s Rack (http://rack.rubyforge.org/) and Python’s WSGI (http://www.wsgi.org/).

    Jack is an implementation of JSGI compatible handlers (to connect to web servers), middleware (to intercept and manipulate requests to add functionality), and utilities (to make using JSGI easier).

    Setup is also breezy. Simply clone Jack into the same directory you cloned Narwhal into:

    git clone git://github.com/tlrobinson/jack.git

    Since you’ve already added narwhal’s bin directory to your path, lets just make a symlink to jackup from there.

    From your narwhal/bin directory:
    ln -s [path/to/jack]/bin/jackup jackup

    Run jackup -h for usage.

    So, what’s next? Where’s Javascript on Rails?

    With Narwhal and Jack, you can start writing basic web apps. Looking at the example.js script in jack/examples we can see the basic request/response structure. Looks familiar huh?

    var Jack = require("jack");
    
    var map = {};
    
    // an extremely simple Jack application
    map["/hello"] = function(env) {
        return [200, {"Content-Type":"text/plain"}, ["Hello from " + env["SCRIPT_NAME"]]];
    }
    
    // apply the URLMap
    var app = Jack.ContentLength(Jack.URLMap(map));
    //...

    While these two pieces are a good start to a vibrant server-side javascript ecosystem, there’s still a long ways to go to before it’ll be on par with Ruby and Python.

    What SSJ needs is its Django/Pylons/Rails/Merb. There are a couple of projects I’ve found in the wild that are using Jack and Narwhal, but they appear to still be in very rapid flux.

    Nitro

    Nitro provides a library of carefully designed middleware and utilities for creating scalable, standards-compliant Web Applications with JavaScript.

    Helma NG

    Helma NG consists of several components that can be used together or alone:

    1) A compact JavaScript runtime environment based on Mozilla Rhino. It adds
    to Rhino a reloading module system that is compatible to the ServerJS
    Securable Module proposal.

    2) An interactive shell with support for autocompletion and history.

    3) A module library implemented in JavaScript, covering basic functionality
    such as extensions to the built-in objects, file I/O, logging, persistence,
    client and server side HTTP support and more.

     
    • nlsmith 2:22 am on June 19, 2009 Permalink

      Nice post.

      You can do REST/JSON with Jaxer (see http://www.aptana.com/jaxer/guide/develop_web_s…), though it's a pain to get running, and Jack would be much better suited to this type of thing.

      As far as the JS on Rails type of thing, check out ActiveJS (http://activejs.org/.) It has a way to go yet, though any contributions would be appreciated. It does have code to make it a ServerJS module, though I haven't seen it in use. All of the modules either work with Jack and Jaxer or could be made to with a little work.

      Another project that might be of interest to you is Persevere (http://persvr.org/.)

      Server-side JavaScript has been around for over 10 years, but it just now is starting to get exciting. In fact, in my day job I work on “classic” ASP in JavaScript. Exciting times.

      Thanks,

      Nathan

    • britg 2:51 am on June 19, 2009 Permalink

      Interesting, thanks for pointing me to those two projects. Perservere looks very interesting, and I immediately associated it with CouchDB because of the RESTful HTTP interface and JSON storage. But two bullets that jumped out at me that I don't know that CouchDB can tout yet is (plus I'm sure there are many more differences):

      # Comet-based data monitoring capabilities through HTTP Channels with Bayeux transport plugin/negotiation support

      # Data-centric capability-based object level security with user management, Persevere is designed to be accessed securely through Ajax with public-facing sites

    • Rob 11:54 am on July 4, 2009 Permalink

      You may also want to look at the open source M/DB:X which is an HTTP-interfaced hybrid JSON/Native XML Database. JSON objects are converted to and stored as XML DOMs which can be analysed, modified, transformed and searched in the XML domain and returned as JSON strings. See http://www.mgateway.com/mdbx.html for more information

c
compose new post
j
next post/next comment
k
previous post/previous comment
r
reply
e
edit
o
show/hide comments
t
go to top
l
go to login
h
show/hide help
esc
cancel