よく使うnode.jsのモジュールを5つ紹介します

ChainZ(クリエイター)
いろいろやってます。

async

async(https://github.com/caolan/async)はもう公式のutilに入れてほしいぐらい使いまくっているモジュールです。node.jsは非同期なので、普段JavaScriptに使うループ式は実用性は低いので、その代わりにasync.each、async.mapなどを使うことが多いです。

async.each

基本形式:

1
2
3
async.each(Array, Callback1(Element, done), Callback2)
async.eachSeries(Array, Callback1(Element, done), Callback2)
// eachSeriesが順番処理です。

Array配列の各要素がElementに渡され、Callback1doneが要素処理のコールバックで、「処理完了」というフラグに使います。doneに第一引数が渡されたら(例えばdone(err))、ループから脱出し、Callback2doneの引数が渡されてコールされます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
var async = require('async');
var fs = require('fs');

var files = [
  "./path/to/file1",
  "./path/to/file2",
  "./path/to/file3"
];

// filesをイテレートする
async.each(files, function(f, done){
   fs.exists(f, function(exist){
      // ファイルが存在しない場合は、doneをコールし、スキップします
      if (! exist) return done();
      fs.readFile(f, function(err, data) {
        // errの場合はerrをdoneに渡して、脱出します。
        if (err) return done(err);

        // 無事に処理が終わったら、ファイルの中身をプリントする
        console.log("Content of " + f + ":");
        console.log(data.toString());
        done();
      });
   });
}, function(err) {
  if (err) console.log(err);
  console.log('Done');
})

Objectをループしたい場合は、Object.keysを利用して、Objectkeyをイテレートします:

1
2
3
4
5
6
7
8
9
10
var player = {
  name: 'Asuka',
  power: 9000,
  sex: female,
};
async.eachSeries(Object.keys(player), function(k) {
  console.log("Playerの" + k + "の値は: " + player[k]);
}, function() {
  console.log("Done");
});

async.waterfall

メソード名waterfallから分かると思うが、滝みたいに順番を処理していくメソードです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function Initialize(callback){
  var app = new App;
  if (app.init()) {
    console.log("app初期化");
    callback(null, app);
  } else {
    callback(new Error('初期化失敗');
  }
}

function Up(app, callback) {
   if (! app.up()) return callback(new Error('アプリ起動できませんでした。');
   callback(null, app);
}

function initModels(app, callback) {
   var models = Models.init();
   if (! models) return callback(new Error('モデル初期化エラー'));
   app.models = models;
   callback(null, app);
}
async.waterfall([
  Initialize,
  Up,
  initModels,
], function(err, app) {
   if (err) return console.log(err);
   console.log("Done");
});

上記は仮の例ですが、アプリの初期化から、起動、モデルの初期化までの各処理を関数化して、waterfallを使ってステップバイステップで実行されます。もしappに対して新しい処理をやりたければ、新しい関数を作成し、waterfallの順番を見て適切なところに入れれば済むのです。middlewareパターンと似ています。

asyncはプログラミングでよく使うロジックメソードがたくさん入っています。node.jsプロジェクトでは欠かせないモジュールとも言えると思います。

commander

コマンドツールを作る定番のモジュールです。apiが非常に使いやすいです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/usr/bin/env node

var program = require('commander');

program
    .version('0.1.0')
    .command('hello')
    .option('-l, --langauge [value]', 'say hello in specified language', null)
    .action(hello)

function hello(options) {
  var lang = options.language || 'english';
  switch (lang.toLowerCase()) {
    case 'english':
       console.log('Hello');
    break;
    case 'japanese':
       console.log('こんにちは');
    break;
    case 'chinese':
       console.log('你好');
    break;
    default:
       console.log("Sorry, I don't know the language.");
    break;
  }
}
program.parse(process.argv);

上記のコードを./sayというファイルとして保存して、コマンドツールで

1
./say hello

を叩くと:

1
Hello

が表示されます。-lオプションをつけてみます:

1
2
3
4
5
6
./say hello -l=japanese
こんにちは
./say hello --language=Chinese
你好
./say hello --language=Kansaiben
Sorry, I don't know the language.

commanderはアプリのコンソールツールを作成するに、非常にパワフルで便利なモジュールです。

String.js

String.jsは(http://stringjs.com/)、JavaScriptのStringオブジェクトに不足しているメソードをよくカバーしてくれるモジュールです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
var S = require('string');

// 繰り返す
S("=").repeat(10).s // ==========

// スペースを取り除く
S("   Hello    ").trim().s // "Hello"

// スラッグ化
S("A awesome post").slugify().s // a-awesome-post

// 文字列を短縮
S("A very very very long title").truncate(11).s // A very very...

// HTMLをエスケープする
S('<div>Hello</div>').escapeHTML().s; //&lt;div&gt;Hello&lt;/div&gt;

// 文字列が存在するかどうか
S('Hello Asuka!').contains('Asuka') // true

// 頭の文字を大文字にする
S("i am a title").capitalize().s // I'm a title
// HTMLのタグを取り除く
S('<header><h1>タイトルです</h1></header>').stripTags().s // タイトルです
S('<header><h1>タイトルです</h1></header>').stripTags('header').s // <h1>タイトルです</h1>

string.jsを使えば、文字列の処理が相当楽になります。おすすめです。

moment.js

momnet.jsは(http://momentjs.com/) フロントとバックエンド両方使える、時間処理のモジュールです。

1
2
3
4
5
6
7
8
// 現在の時間を取得
moment().format('MMMM Do YYYY, h:mm:ss a'); //2015-05-31T19:23:03+09:00

// 相対時間
moment("20150529", "YYYYMMDD").formNow(); // 

// カレンダー時間
moment().add(1, 'days').calendar();

公式サイトで詳しい説明が載ってあるので、もっと知りたい方は公式サイトを参考してください。

node-fs-extra

fs-extra(https://github.com/jprichardson/node-fs-extra)名前通り、ネイティヴモジュールfsを拡張したバージョンです。必要とは言えないが、DRYを求める人には便利なツールだと思います。個人でよく使っています。

fs.copy

ファイルを指定した場所に保存する:

1
2
3
4
5
var fs = require('fs-extra');
fs.copy("/source/file", "/dest/file", function(err){
  if (err) return console.log(err);
  console.log("/source/fileを/dest/fileにコピーしました");
});

fs.ensureDir

フォルダを確保する:

1
2
3
4
5
6
7
fs.ensureDir("/create/me", function(err){
  if (err) return console.log(err);
  fs.writeFile("/create/me/text.txt", "Hello World", function(err) {
    if (err) return console.log(err);
    console.log("Done");
  });
});

そのほかにも便利なメソードがたくさんあります。公式のドキュメントを参考してください。

まとめ

node.jsには優秀なモジュールがいっぱい揃っています。モジュールをうまく使えば開発が倍速になります。もちろん、使いすぎるとモジュール依存が強くなって、保守には難しくなるリスクもあります。ここで紹介したモジュールはどれも安定しているので、プロダクションに使っても問題ないと思います。