Windows ではじめてみる Node.js

Node.js といえば発表された当初、イベント駆動、ノンブロッキングI/O、スケーラブルネットワークブログラミング、といった部分が注目され非常に話題になりました。 フロントエンド技術の興隆目覚しい昨今においては、Sass や CoffeeScript のコンパイルを自動化する Grunt や Gulp といったタスクランナーを動かすための開発環境インフラとして大きな役割をはたしています。
今回はそんな node.js の基本的な利用方法についてまとめてみました。

Node.js のインストールとバージョン管理

発表当初、試すのにも敷居の高さがあった Node.js ですが、今では Windows でも容易に利用できるようになってます。 Windows で Node.js をインストールする一番簡単な方法は、以下公式サイトにあるインストーラーを使用する方法です。 ダウンロードして実行するのみでインストールは完了します。

node
http://nodejs.org/download/

しかし、Node.js はバージョンアップのサイクルが非常に早く、バージョンによっては動作しないモジュールがあった場合、バージョン変更するのが非常に面倒です。 そこで Node.js のインストールとバージョン変更を簡単に行うことができるバージョン管理ツールを使用してみます。 バージョン管理ツールには以下のものがあります。

  • nodist
    • Windows 専用のバージョン管理ツール
  • nvm
    • Mac OSX/Linux 用のバージョン管理ツール
  • nvmw
    • Windows 向けの nvm、Python のインストールが必要
  • nodebrew
    • Perl製のバージョン管理ツール、Mac OSX/Linux 用

ちなみにマイナーバージョンが、v0.2, v0.4 のように偶数値のものが安定板、v0.3, v0.5 のように奇数値のものが開発版という位置づけになります。

nodist によるインストールとバージョン管理

今回は Windows 専用のバージョン管理ツール「nodist」を使用してみます。 GitHub よりソースコードを取得します。

  1. git clone https://github.com/marcelklehr/nodist.git


Git がインストールされてない場合は https://github.com/marcelklehr/nodist より “Donwload ZIP” をクリックし、ソースコード一式を取得し解凍します。

次に環境変数の設定を行います。ソースコードの展開先を c:\ide\nodist とした場合、コマンドプロンプト(もしくは Git の Bash)より以下のように入力します。

  1. setx /M NODIST_PREFIX "c:\ide\nodist"
  2. setx /M PATH "%NODIST_PREFIX%\bin;%PATH%"


コマンドプロンプトを一旦閉じ再起動すると環境変数が適用されますので、その状態でNode.js のインストールを行います。

  1. $ nodist update


インストールされた node.js のバージョンを確認します。

  1. $ node -v
  2. v0.10.35


最新の安定版がインストールされてるいることを確認できます。試しに旧バージョン(v0.10.2)をインストールしてみます。

  1. $ nodist + v0.10.2


nodist と入力するとインストールされてるバージョンの一覧と適用されてるバージョンの確認ができます。

  1. $ nodist
  2. 0.10.2
  3. > 0.10.35 (global)


v0.10.35 が適用されてることが分かります。バージョンを切り替えるには以下のように入力します。

  1. $ nodist v0.10.2


バージョン番号を指定せず、最新の安定版を適用するには stable と指定します。

  1. $ nodist stable


特定のバージョンをアンインストールするにはバージョン番号の前に – を指定します。

  1. $ nodist - v0.10.2

Node.js を対話モードで使用してみる

Node.js を対話モードのREPL(Read eval print loop:対話的実行環境)で動かしてみます。 node と入力します。

  1. $ node
  2. >


キー入力待ち状態になります。計算式を入力すると計算結果が表示されます。

  1. > 523*3
  2. 1569


JavaScript の命令も使用できます。

  1. > 'node.js'.toUpperCase()
  2. NODE.JS


プログラムを実行してみます。以下コードを hello.js という名前で作業フォルダに保存します。

  1. var msg = 'Hello Node.js !';
  2. console.log(msg)


コマンドプロンプトに戻り(Ctrl+Cを2回もしくは .exit と入力すると戻れます)以下のよう入力すると実行できます。

  1. $ node hello.js
  2. Hello Node.js !


対話モードで .help と入力すると使用できるコマンド一覧が表示されます。

  1. > .help
  2. .break Sometimes you get stuck, this gets you out
  3. .clear Alias for .break
  4. .exit Exit the repl
  5. .help Show repl options
  6. .load Load JS from a file into the REPL session
  7. .save Save all evaluated commands in this REPL session to a file

モジュールの読み込み

require 関数を使用するとプログラム内で他の js ファイル(モジュール)を読み込むことができます。 また、モジュールは exports オブジェクトを通じ値やメソッドを定義することができます。

指定した名前に挨拶する hello_name モジュール(hello_name.js)を作成してみます。

  1. exports.setName = function(name){
  2. this.name = name;
  3. }
  4. exports.hello = function(){
  5. console.log('Hello,', this.name, '!');
  6. }


hello_name モジュールを呼び込み、’Taro’ に挨拶する hello_taro モジュール(hello_taro.js)を作成します。

  1. var helloName = require('./hello_name'); // 自作モジュールの場合は path の指定は必須
  2. helloName.setName('Taro');
  3. helloName.hello();


hello_taro.js を実行すると Hello, Taro ! と表示されます。

  1. $ node hello_taro.js
  2. Hello, Taro !

標準モジュールを使用してみる

node.js に最初から組み込まれている標準モジュールをいくつか使用してみます。

  • http
    • HTTP サーバやクライアント機能を提供します
  • fs
    • ファイルシステムへのアクセス機能を提供します
  • net
    • TCP 通信によるネットワークサーバやクライアント機能を提供します

HTTP サーバを動かす

http モジュールは、HTTP サーバやクライアント機能を提供します。 下記コードを http.js というファイル名で保存します。

  1. var http = require('http');
  2. var server = http.createServer();
  3. server.on('request', function(req, res){
  4. res.writeHead(200, {'Content-Type':'text/html'});
  5. res.write('<h1>Hello Node !</h1>');
  6. res.end();
  7. });
  8. server.listen(8080);
  9. console.log('Server running on 8080');


http.js を実行します。

  1. $ node http.js
  2. server started on 8080

ブラウザより http://localhost:8080 にアクセスすると Hello Node ! と表示されます。

Web API を利用する

http モジュールを使用し Web API を利用してみます。 http://nodejs.org/ のはてブ数を取得してみます。 下記コードを webapi.js というファイル名で保存します。

  1. var http = require('http');
  2. http.get(
  3. 'http://api.b.st-hatena.com/entry.count?url=http://nodejs.org/',
  4. function(res){
  5. res.setEncoding('utf-8');
  6. res.on('data', function(chunk){
  7. console.log('nodejs.org のはてブ数 : ' + chunk);
  8. });
  9. }
  10. ).
  11. on('error', function(e){
  12. console.log('ERROR', e.message);
  13. });


webapi.js を実行すると http://nodejs.org/ のはてブ数が表示されます。

  1. $ node webapi.js
  2. nodejs.org のはてブ数 : 600

ファイルシステム にアクセスする

fs モジュールは、ファイルシステムへのアクセス機能を提供します。 下記コードを fs.js というファイル名で保存します。

  1. var fs = require('fs');
  2. fs.readFile('fs.txt', 'utf-8', function(err, data){
  3. if(err){
  4. return console.log(err);
  5. }
  6. else{
  7. console.log(data);
  8. }
  9. });


fs.js を実行すると fs.txt が無いためエラーが表示されます。

  1. $ node fs.js
  2. エラーだよ
  3. { [Error: ENOENT, open '・・・fs.txt']
  4. errno: 34,
  5. code: 'ENOENT',
  6. path: '・・・fs.txt' }


fs.txt を以下のように作成します。

  1. ファイルの読み取り成功!


fs.js を再度実行すると、fs.txtの中身が表示されます。

  1. $ node fs.js
  2. ファイルの読み取り成功!

TCP サーバを動かす

net モジュールは TCP 通信によるネットワークサーバやクライアント機能を提供します。 下記コードを net.js というファイル名で保存します。

  1. var net = require('net');
  2. var server = net.createServer(function(socket){
  3. console.log('connected!');
  4. socket.on('data', function(data){
  5. socket.write('you said ' + data + '\n');
  6. });
  7. socket.on('end', function(){
  8. console.log('disconnected');
  9. });
  10. });
  11. server.listen(8111);
  12. console.log('server start listening on 8111')


net.js を実行します。

  1. $ node net.js
  2. server start listening on 8111

telnet で localhost に接続後、適当にキー入力しエンターすると入力した文字が表示されます。

node

npm でサードパーティ製モジュールをインストールする

npm(Node Package Manager)を使用することで、サードパーティ製のモジュールをインストールすることができます。 以下のモジュールをインストールして使用してみます。

  • request
    • HTTP リクエスト処理の簡潔な記述を可能にする
  • async
    • 非同期処理の簡潔な記述を可能にする

request モジュールをインストールしてみます。

  1. $ node install request

作業フォルダに node_modules フォルダが生成され request モジュールが配置されます。

-g オプションを付けてインストールするとグローバル環境に配置され、異なる作業フォルダからもモジュールを利用できるようになります。

  1. $ node install -g request

パッケージ定義ファイルを利用しインストールする

パッケージ定義ファイル package.json に利用するモジュールを定義しインストールすることもできます。 プロジェクトフォルダを作成し、その中に package.json を定義してみます。

  1. mkdir sample_proj
  2. cd sample_proj
  3. npm init


npm init と入力すると対話形式で、package.json を作成することができます。 ここではとりあえず何も入力せず全てエンターします。 対話入力が終わると以下内容の package.json が生成されます。

  1. {
  2. "name": "sample_proj",
  3. "version": "0.0.0",
  4. "description": "",
  5. "main": "index.js",
  6. "scripts": {
  7. "test": "echo \"Error: no test specified\" && exit 1"
  8. },
  9. "author": "",
  10. "license": "ISC"
  11. }


この package.json に dependencies 属性を追記し、インストールしたいモジュール名とバージョンを指定します。 ここでは request と async を指定します。

  1. "dependencies" : {
  2. "request": ">=1.0.0", // 1.0.0以上
  3. "async": "*",
  4. }


npm install と入力すると package.json に定義されたモジュールがインストールされます。

  1. $ npm install

指定 URL の HTML を読み込む

request モジュールを使用し、指定した URL の HTML を読み込み表示してみます。 下記コードを request.js というファイル名で保存します。

  1. var req = require('request');
  2. req.get('http://www.yahoo.co.jp', function(err, res ,body){
  3. console.log(body);
  4. });


request.js を実行すると、指定した URL の HTML が表示されます。

  1. $ node request.js
  2. ・・・
  3. </center>
  4. </body>
  5. </html>
  6. <!-- p05.f12.top.ssk.yahoo.co.jp Wed Jan 28 02:02:08 JST 2015 -->

非同期処理を分かりやすく書く

非同期処理をコールバックで定義するとネストが深くなり、可読性が悪くなりがちです。 async モジュールを使用し非同期処理の記述をすっきりさせる事ができます。

まずは順次処理から。下記コードを series.js というファイル名で保存します。

  1. var async = require('async');
  2. async.series(
  3. [
  4. function(callback){
  5. console.log('start-a');
  6. setTimeout(function(){
  7. console.log('done-a');
  8. callback(null, 'result-a')
  9. }, 1000);
  10. },
  11. function(callback){
  12. console.log('start-b');
  13. setTimeout(function(){
  14. console.log('done-b');
  15. callback(null, 'result-b')
  16. }, 500);
  17. }
  18. ],
  19. function(error, result){
  20. console.log(result);
  21. }
  22. );


series.js を実行すると、定義した順番に処理が実行されてることが確認できます。

  1. $ node series.js
  2. start-a
  3. done-a
  4. start-b
  5. done-b
  6. [ 'result-a', 'result-b' ]


次に並列処理を書いてみます。series の記述箇所を parallel に置き換えた下記コードを parallel.js というファイル名で保存します。

  1. var async = require('async');
  2. async.parallel(
  3. [
  4. function(callback){
  5. console.log('start-a');
  6. setTimeout(function(){
  7. console.log('done-a');
  8. callback(null, 'result-a')
  9. }, 1000);
  10. },
  11. function(callback){
  12. console.log('start-b');
  13. setTimeout(function(){
  14. console.log('done-b');
  15. callback(null, 'result-b')
  16. }, 500);
  17. }
  18. ],
  19. function(error, result){
  20. console.log(result);
  21. }
  22. );


parallel.js を実行すると、処理の呼び出しが先行して行われ、処理が終了した順にコールバックが実行されてることが確認できます。

  1. $ node parallel.js
  2. start-a
  3. start-b
  4. done-b
  5. done-a
  6. [ 'result-a', 'result-b' ]


async.series や async.parallel の引数には配列を指定しましたが JSON を指定することもできます.

  1. var async = require('async');
  2. async.parallel(
  3. {
  4. a: function(callback){
  5. console.log('start-a');
  6. setTimeout(function(){
  7. console.log('done-a');
  8. callback(null, 'result-a')
  9. }, 1000);
  10. },
  11. b: function(callback){
  12. console.log('start-b');
  13. setTimeout(function(){
  14. console.log('done-b');
  15. callback(null, 'result-b')
  16. }, 500);
  17. }
  18. },
  19. function(error, result){
  20. console.log(result);
  21. }
  22. );


この場合、JSON 形式で処理結果を受け取ることができます。

  1. $ node parallel.js
  2. start-a
  3. start-b
  4. done-b
  5. done-a
  6. { b: 'result-b', a: 'result-a' }

最後に

以上、基本的な利用方法のまとめでした。 node.js 対応の PaaS もめずらしくない世の中ですので、機会があったら利用していきたいと思います。

サンプルプログラム一式は以下にあります。
https://github.com/cyokodog/JS_STUDY