6 Must Have Node.js Modules

So you’re thinking about using node.js: awesome. If you’re new to the community you’re probably thinking “what’s the best node.js module / library for X?” I think it’s really true when experienced language gurus say “80% of your favorite language is your favorite library.” This is the first in a series of articles will give you a high-level overview of some of our favorite node.js libraries at Nodejitsu. Today we’ll take a look at these libraries:

 

  1. cradle: A high-level, caching, CouchDB library for Node.js
  2. findit: Walk a directory tree in node.js
  3. node_redis: Redis client for node
  4. node-static: RFC2616 compliant HTTP static-file server module, with built-in caching.
  5. optimist: Light-weight option parsing for node.js
  6. xml2js: Simple XML to JavaScript object converter.

 

cradle: A high-level, caching, CouchDB library for Node.js

If you’re using CouchDB you should be using cradle. Cradle stands above the other CouchDB libraries in the node.js community: it has a robust LRU (least recently used) cache, bulk document processing, and a simple and elegant API:

 

//
// Create a connection
//
var conn = new(cradle.Connection)('http://living-room.couch', 5984, {
  cache: true,
  raw: false
});

//
// Get a database
//
var database = conn.database('newyorkcity');

//
// Now work with it
//
database.save('flatiron', {
  description: 'The neighborhood surrounding the Flatiron building',
  boundaries: {
    north: '28 Street',
    south: '18 Street',
    east: 'Park Avenue',
    west: '6 Avenue'
  }
}, function (err, res) {
  console.log(res.ok) // True
});

 

 

findit: Walk a directory tree in Node.js

A common set of problems that I see on the nodejs mailing list are advanced file system operations: watching all the files in a directory, enumerating an entire directory, etc. Recently, when working on my fork of docco to respect directory structure in the documentation produced I needed such a feature. It was surprisingly easy:

 

var findit = require('findit');

findit.find('/dir/to/walk', function (file) {
  //
  // This function is called each time a file is enumerated in the dir tree
  //
  console.log(file);
});

 

 

node_redis: Redis client for Node.js

There have been a lot of redis clients released for node.js. The question has become: which client is the right one to use? When selecting an answer to this question for any library you want to look for a few things including: the author, the recent activity, and the number of followers on GitHub. In this case the author is Matt Ranney, a member of the node.js core team. The most recent commit was yesterday, and the repository has over 300 followers.

Redis is really fast, and extremely useful for storing volatile information like sessions and cached data. Lets take a look at some sample usage:

 

var redis = require("redis"),
    client = redis.createClient();

client.on("error", function (err) {
  console.log("Error " + err);
});

client.set("string key", "string val", redis.print);
client.hset("hash key", "hashtest 1", "some value", redis.print);
client.hset(["hash key", "hashtest 2", "some other value"], redis.print);
client.hkeys("hash key", function (err, replies) {
  console.log(replies.length + " replies:");
  replies.forEach(function (reply, i) {
      console.log("    " + i + ": " + reply);
  });
  client.quit();
});

 

 

node-static: RFC2616 compliant HTTP static-file server module, with built-in caching

I bet you’re wondering “What the $%^@ is RFC2616?” RFC2616 is the standards specification for HTTP 1.1, released in 1999. This spec is responsible for outlining how (among other things) files should be served over HTTP. Thus, when choosing a node.js static file server, its important to understand which libraries are standards compliant and which are not: node-static is. In addition, it has some great built-in caching which will speed up your file serving in highly concurrent scenarios.

Using node-static is easy, lets make a static file server in 7 lines of Javascript:

 

var static = require('node-static');

//
// Create a node-static server instance to serve the './public' folder
//
var file = new(static.Server)('./public');

require('http').createServer(function (request, response) {
  request.addListener('end', function () {
    //
    // Serve files!
    //
    file.serve(request, response);
  });
}).listen(8080);

 

 

optimist: Light-weight option parsing for Node.js

One of the great things about node.js is how easy it is to write (and later publish with npm) simple command-line tools in Javascript. Clearly, when one is writing a command line tool one of the most important things is to have a robust command line options parser. Our library of choice for this at Nodejitsu is optimist by substack.

Lets take a look at a sample CLI script reminiscent of FizzBuzz:

 

#!/usr/bin/env node
var argv = require('optimist').argv;

if (argv.rif - 5 * argv.xup > 7.138) {
  console.log('Buy more riffiwobbles');
}
else {
  console.log('Sell the xupptumblers');
}

 

Using this CLI script is easy:

$ ./node-optimist.js --rif=55 --xup=9.52
Buy more riffiwobbles

$ ./node-optimist.js --rif 12 --xup 8.1
Sell the xupptumblers

This library has support for -a style arguments and --argument style arguments. In addition any arguments passed without an option will be available in argv._. For more information on this library check out the repository on GitHub.

 

xml2js: Simple XML to Javascript object converter

Writing clients in node.js for APIs that expose data through JSON is almost too easy. There is no need for a complex, language-specific JSON parsing library that one might find in languages such as Ruby or Python. Just use the built-in Javascript JSON.parse method on the data returned and voila! you’ve got native Javascript objects.

But what about APIs that only expose their data through XML? You could use the native libxmljsmodule from polotek, but the overhead of dealing with individual XML nodes is non-trivial and (in my opinion) can lead to excess complexity. There is another, simpler option: the lesser knownxml2js library available on npm and GitHub.

Lets suppose that we had some XML (/me dies a little inside):

 

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <child foo="bar">
    <grandchild baz="fizbuzz">grandchild content</grandchild>
  </child>
  <sibling>with content!</sibling>
</root>

 

Parsing this using xml2js is actually surprisingly easy:

 

var fs = require('fs'),
    eyes = require('eyes'),
    xml2js = require('xml2js');

var parser = new xml2js.Parser();

parser.on('end', function(result) {
  eyes.inspect(result);
});

fs.readFile(__dirname + '/foo.xml', function(err, data) {
  parser.parseString(data);
});

 

The output we would see is:

 

{
  child: {
    @: { foo: 'bar' },
    grandchild: {
      #: 'grandchild content',
      @: { baz: 'fizbuzz' }
    }
  },
  sibling: 'with content!'
}

 

If you haven’t already noticed, xml2js transforms arbitrary XML to JSON in the following way:

  • All entity tags like <child> become keys in the corresponding JSON.
  • Simple tags like <sibling>with content</sibling> become simple key:value pairs (e.g. sibling: ‘with content!’)
  • More complex tags like <child>... and <grandchild>... become complex key:value pairs where the value is an Object literal with two important properties:
    1. @: An Object representing all attributes on the specified tag
    2. #: Any text content for this XML node.

This simple mapping can greatly simplify the XML parsing logic in your node.js application and is worth checking out if you ever have to deal with the three-headed dog we all love to hate.

 

Just getting started

This is the first in a series of articles where we will outline at a high level the best-of-the-best for modules, libraries and techniques in node.js that you should be aware of. If you’re interested in writing your own node.js modules and publishing them to npm, check out isaacs new article: How to Module over at howtonode.org.

为什么要迁移到Websphere, Weblogic, and JBoss? Resin用着很好。

我们的项目在 Dual Xeon 3.0 GHz with 4 GB RAM and 36 GB SCSI/RAID5下的Resin Pro可以轻松跑415 avg. req/s ,但迁移到 JBoss/Tomcat后就降低到225 avg. req/s.

我不知道Resin clsutering或 session replication有多好,但我会说,他们可能是很好的。

关于编译resin的错误处理。

不知道什么时候开始,resin4就无法编译

错误1:aclocal: couldn’t open directory `m4′: No such file or directory

[root@datanode2 resin-pro-4.0.36]# make
CDPATH=”${ZSH_VERSION+.}:” && cd . && aclocal -I m4
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
LANGUAGE = (unset),
LC_ALL = (unset),
LANG = “en.UTF-8”
are supported and installed on your system.
perl: warning: Falling back to the standard locale (“C”).
aclocal: couldn’t open directory `m4′: No such file or directory
make: *** [aclocal.m4] Error 1

处理办法在resin目录下建立m4目录。

mkdir m4

问题解决。

错误2:Makefile.in not found

[root@datanode2 resin-pro-4.0.36]# make
cd . && automake –foreign –ignore-deps
configure.ac:1568: required file `../pro/modules/c/src/Makefile.in’ not found
configure.ac:1568: required file `../pro/modules/c/src/resin/Makefile.in’ not found
configure.ac:1568: required file `../pro/modules/c/src/resinssl/Makefile.in’ not found
make: *** [Makefile.in] Error 1

解决办法:
mkdir ../pro
cp -r modules ../pro/

 

以上2个错误应该跟新版的resin没有多大关系,不过可能是我的编译器比较旧吧。