Here are my notes from learning node.js over the winter vacation. You can think of this post as asking me what resources did you find helpful in learning node.js? There is a lot of node.js stuff out there, but few posts on what is noteworthy, popular or tricky - I am sick of seeing posts explaining what node.js is and showing me the same five lines of code.

Structuring code

I recommend reading the series on control flow in node.js from Tim Caswell: Scope and this are different/tricky in JS, read this and this. Update Feb 2011: Update Jan 2011: Inheritance patterns in Javascript (using a modern style that optimizes well when using the Google Closure compiler). You'll probably run into problems with assigning values if you use the class pattern. The problems is that adding variables in the prototype makes them shared among instances. You'll have to explicitly initialize any per-instance variables in the constructor, or otherwise the object instance will keep accessing the prototype property => property acts like it would be static. Obvious in retrospect, but hindsight makes fools of us all.

Modules

Have a look at the node.js modules page on github for a comprehensive list of modules. Install npm to install packages. Or don't, just drop the repos in a subdirectory and use require, since require in node.js is flexible.

Debugging

Simply printing out stuff can be done using sys.puts(string) (first "var sys = require('sys')"). Since you are on V8, you can use JSON.stringify(object) natively. console.log() also works, it automatically prettyprints objects, but only one level deep (no nested objects). For those rare occasions where JSON.stringify(object) fails (e.g. due to recursion) you can use require('util').inspect(object) as an alternative.

Setting up the server

Update: Here is how I got Node.js up and running on Centos 5 with nginx + monit. First, you'll want to decide how you want to build your applications - will you use node.js for the whole stack, or will you mix it with more familiar scripting languages. If you want to mix two technology stacks, I strongly recommend NOT trying to combine node.js with other web app stacks using subdomains, since you'll have an unlimited amount of trouble due to the same origin policy enforcement that is built into all browsers. You can either solve that problem for all browsers:
  • IE6/7 has no mechanism,
  • IE8/9 has XDomainRequest,
  • Mozilla/Chrome/Opera have XMLHttpRequest Level 2 (note that level 2 is needed for cross-domain support).
Or you can solve the problem on the server:
  1. by only using node.js for all of your stack, running a bare node.js server
  2. by running a mixed stack using Nginx or Apache to proxy node.js requests
I'm not quite ready to start from scratch, given the productivity that my non-node-js stack gives; I did the mixed route with Apache which is adequate for trying things out. If you want to scale a bit more, you'll want to setup Nginx. You can proxy requests from Apache to Node.js (second example), or do a rewrite. You'll want to use a subdirectory for node.js requests so that you don't have to deal with the same origin policy. Here is what I did: bash <VirtualHost *:80> ServerAdmin webmaster@localhost DocumentRoot /path/to/www/ ServerName example.com ProxyPass /node/ http://127.0.0.1:8001/ retry=0 timeout=120 <Proxy *> Allow from all </Proxy> </VirtualHost> The "retry=0" parameter prevents Apache from waiting 60 seconds if a node.js response fails (e.g. due to server restart).

Comet with node.js

Have a look at socket.io (github page) for streaming. In my testing, I couldn't get it to work with IE9 (sending stuff) and Chrome seemed to keep dropping connections. Firefox worked solidly and Chrome after I set it to reconnect, but I couldn't figure out why IE9 was not working (it could receive messages, but sending them did not seem to work..). I am sure that socket.io will get there, reliable real-time transmission in all major browsers just isn't quite yet a problem that has been solved neatly. There are still issues to resolve, it seems. To be fair, that's for cross-domain requests. If you use socket.io, you will probably want to implement your own abstractions over it, since you'll want to do something with channels. There is the broadcast(message, list_of_excluded_user_ids) method, but you probably want to have more fine-grained control which can be done via additional abstractions. There are also two other promising comet projects: Push-it and Faye. Push-it (github, stackoverflow) is built on top of socket.io. Faye (homepage, github) also looks interesting but I spotted this to-do on the repo: "Detect failed WebSocket connection and fall back to polling transports" - e.g. it doesn't seem to work in non-Websocket browsers (IE6/IE7), something I would like to have (in fact right now, Dec 2010 WebSockets is disabled in newer FF 4 builds and Opera 11 due to security concerns).

Connecting to MySQL

Comments

Will Tran: http://www.devcomments.com/Update-benchmarks-for-Node-js-MySQL-drivers-at290013.htm

Jagdish Hiray: This is really good article. Have you come across way to call server side node js from client side js?

Thank you.

Mikito Takada: Yeah, you can do that either by exposing an API, or using something like nowjs, which does the wrapping for you.

PS - for more stuff, read my book: http://book.mixu.net/

enz54: hi mikito, quick question I'm develop a website using express and I'm having difficulty deploying online. Do you know any hosting companies out there? Is it crucial that the host support node.js or you can use anyone? I tried appfog but every time I update my app I've got error: name: VmcError, endpoint: PUT:/apps/:name, statusCode: 500, code: 310, description: Staging failed: 'Staging task failed: Staging plugin failed: /opt/cloudfoundry/vcap/staging/lib/vcap/staging/plugin/node/plugin.rb:80:in guess_main_file': Unable to determine Node.js startup command (RuntimeError) from /opt/cloudfoundry/vcap/staging/lib/vcap/staging/plugin/node/plugin.rb:29:indetect_start_command' from /opt/cloudfoundry/vcap/staging/lib/vcap/staging/plugin/node/node_autoconfig.rb:27:in setup_autoconfig' from /opt/cloudfoundry/vcap/staging/lib/vcap/staging/plugin/node/plugin.rb:14:inblock in stage_application' from /opt/cloudfoundry/vcap/staging/lib/vcap/staging/plugin/node/plugin.rb:9:in chdir' from /opt/cloudfoundry/vcap/staging/lib/vcap/staging/plugin/node/plugin.rb:9:instage_application' from /opt/cloudfoundry/vcap/stager/bin/run_plugin:19:in `'

Your help will be just awesome!!!!

cheers eric