Node.jsをとりあえず始めるにあたって現実的に必要だった知識


## はじめに
この夏、Node.jsを始めようと思い立ったときに調べたことをメモしました。
「お前こんなことも知らなかったの！？」ということがばれるのは恥ずかしいですが、同じところで立ち止まってる人のお役に立てば。

##下準備
### Node.jsのバージョン管理ツールの導入  
#### メリット
異なるバージョンのnode.jsを手軽に共存させられる

#### 代表的なもの  
- nvm
- nodebrew
- nave

#### nodebrewでnode.js(+npm)のインストール
既にnode.jsをインストールしている場合は一旦アンインストールする必要あり

- node.jsのアンインストール

	- [Mac OS X から Node.js をアンインストールする方法](http://d.sonicjam.co.jp/post/52541343939)
	- [node.jsのアンインストール](http://stackoverflow.com/questions/9044788/how-do-i-uninstall-nodejs-installed-from-pkg-mac-os-x)  
<br />

- nodebrew + node.jsインストールの流れ

	- [node.js 入れるなら nodebrew が超簡単](http://tacamy.hatenablog.com/entry/2013/02/10/141434)
	- [[Front end] Node.js: nodebrew で node.js をインストールする](http://www.d-wood.com/blog/2013/10/30_4963.html)
 
	- npmはnode.jsのパッケージに含まれている  
<br />

- nodebrewの使い方  

|command |概要|
|:---:|:---:|
|nodebrew ls|管理しているnode.jsのバージョン一覧+現在使用中のバージョンを表示|
|nodebrew use vバージョンナンバー|使用するバージョンを指定|
|nodebrew selfupdate|nodebrew の update|
<br />

### パッケージ管理プログラムnpmの使い方

- 現在のディレクトリにインストール  

```  
npm install パッケージ
```
- グローバル環境にインストール  

```  
npm install -g パッケージ
```
<br>
  
## Node.jsの初歩
### モジュールの読込, モジュールの変数および関数の使用
#### モジュールの読み込み  
		
```javascript:
var http = require('http');  
```

#### モジュールの変数および関数の使用
- 呼ばれる側:  
他のファイルから関数hogeを使用したい場合は  

```javascript:
function hoge(){
	// 処理
				
}
exports.hoge = hoge;
```	  

- 呼ぶ側:  
他のファイルからhogeを呼ぶときは 

```javascript
var foo = require('./ファイル名');  
foo.hoge();  
```

<br>

### 自作モジュールでnode_modulesディレクトリを使う
- node_modules下にモジュールディレクトリを作る
- モジュールディレクトリ内にpackage.jsonファイルを作り、

```javascript:package.json
{
	"main": "./customModule.js"
}
```

のように、モジュールのメインファイルを指定する。
<br>

### Globalオブジェクト
[公式ドキュメント](http://nodejs.jp/nodejs.org_ja/api/globals.html)を参照。

#### __dirname
- 現在実行されているスクリプトが存在するディレクトリの名前
- __dirname は実際はグローバルではなく、各モジュール毎のローカル

#### __filename
- 実行されているコードのファイル名(絶対パス)。
- __filename は実際はグローバルではなく、各モジュール毎のローカル

#### require, module.exports, exports
- CommonJSのモジュールシステムの規格に準拠  
<br>

### よく使う標準モジュールの使用例
標準モジュールについては[Node.js公式サイト](http://nodejs.jp/nodejs.org_ja/api/index.html)にAPIリファレンスあり。  

#### http

```javascript:
var http = require('http');
http.createServer(function(req, res){
	// 処理
	switch (req.method){
		case 'POST':
			var data;
			req.setEncoding('utf8');
			req.on('data', function(dataChunk) {
				// データ受信中の処理
				data += dataChunk;	
			});
			req.on('end', function() {
				// データ受信完了後の処理
				console.log(data);
				res.end('finished');
			});
			break;
			
		case 'GET':
			res.setHeader({'Content-Type', 'text/plain; charaset="utf-8"'});
			res.write('hello');
			res.end();
			break;
		
	・・・
	// 必ずres.end()でレスポンスを終了させること
	}
}).listen(ポート番号);
```

#### url

```javascript:
var url = require('url');
var path = url.parse(urlStr).path;
```

#### fs

```javascript:
var fs = require('fs');
	
// ファイルの非同期読み込み
fs.readFile('./filename', function(err, data) {
	if(err) throw err;
	console.log(data);
});

// ディレクトリの監視
fs.watchFile('./watch', function() {
	// 処理
	・・・
				
});

// ファイル名変更
fs.rename(oldPath, newPath, callback);

// Stream
var stream = fs.createReadStream(path);  // pathのファイルをインクリメンタルに読み出し
stream.pipe(res);  // resにstreamのデータを書き込み(res.end()も内部で呼び出す)
stream.on('error', function(err) {
	res.statusCode = 500;
	res.end('Internal Server Error');
});

// stat
fs.stat(path, function(err, stat) {
	// pathの存在をチェック
	// (ファイルがなければerr.codeにENOENTが入ってる)
		
	// statはファイルの詳細情報
	・・・
});
```

#### events (イベントエミッタの作成)  

```javascript:
// イベント登録
var events = require('events');

var EventEmitter = require('events').EventEmitter;
var customEmitter = new EventEmitter();
customEmitter.on('customEvent', function(){
	console.log('カスタムイベント発生');
});

// イベント発行
customEvent.emit('customEvent');  

// リスナの削除
customEmitter.removeListener('customEvent', function(){
	console.log('カスタムイベント発生');
});
```

#### util

```javascript:
var utils = require('util');
var events = require('events');

// プロトタイプメソッドの継承
util.inherits(MyStream, events.EventEmitter);	
// これと同じ
MyStream.prototype = new events.EventEmitter();
```

#### https    

```javascript:
var https = require('https');
var fs = require('fs');

var options = {
  	key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),
  	cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem')
};

https.createServer(options, function (req, res) {
  	res.writeHead(200);
  	res.end("hello world\n");
}).listen(8000);
```	

<br>

## DB関連
### MongoDB

#### MongoDBのインストール
http://docs.mongodb.org/manual/tutorial/install-mongodb-on-os-x/

#### 起動前の準備  
- データディレクトリを作成しておく。  

```		
mkdir -p /data/db  
```

- [下記コマンドで、ディレクトリの権限を自分に変更しておく。](http://stackoverflow.com/questions/10166612/mongodb-installation-failure-to-run-mongod)  

```
sudo chown -R <your-username> /data/db  
```

- 起動

```
mongod
```

#### Node.jsのモジュール「Mongoose」  
MongoDBを扱うモジュールはいくつかあるが、Mongooseが使いやすそう。

- インストール

```
npm install mongoose
```

- 使い方  
Mongooseの使い方は下記の記事を参考にした。
	- [Mongoose Quick Start](http://mongoosejs.com/docs/index.html)
	- [node.js から MongoDB にアクセス (Mongoose の紹介)](http://krdlab.hatenablog.com/entry/20110317/1300367785)

<br>
### Redis
#### インストール

```
brew install redis
```

#### 起動

```
redis-server
```

#### Node.jsのモジュール「node_redis」
- インストール

```
npm install redis
```

- 使い方  
下記資料を参考にした。

#### 参考資料
- [node_redis](https://github.com/mranney/node_redis)
- [node.jsでRedisを使ってみる【準備編】](http://yutapon.hatenablog.com/entry/2013/07/07/011645)
- [redisとnode.js](http://sanami-mikio.tumblr.com/post/14397843702/redis-node-js)
- [node-redisを入れてみるメモ](http://qiita.com/toshirot/items/63de388bf40cff40a096)

 


<br>

## Express
### Expressとは
- Node.jsのWebアプリケーションフレームワーク
- 2014年にExpress 4がリリースされた

### Express 4.x
- 3.xから変更点が多い
	- [New features in 4.x](https://github.com/strongloop/express/wiki/New-features-in-4.x)
	- [Migrating from 3.x to 4.x](https://github.com/strongloop/express/wiki/Migrating-from-3.x-to-4.x)
	- [express4でRESTful API作る](http://yutapon.hatenablog.com/entry/2014/04/29/124657) 

#### Express 4.xでのひな形作成
- Express 4からはひな形作成にexpress-generatorという別パッケージが必要になった  

```
npm install -g express-generator  # これ入れるとexpressコマンドが使えるようになる
express /tmp/foo && cd /tmp/foo  # fooプロジェクトを作成
npm install # package.jsonに記述されてる依存モジュールを入れる
npm start # アプリケーション起動
```

#### 4.xでの主な変更
- [公式ドキュメント](https://github.com/strongloop/express/wiki/Migrating-from-3.x-to-4.x)

##### app.router
- Express 3.xで必須だった[app.use(app.router)の記述が必要無し](https://github.com/strongloop/express/wiki/New-features-in-4.x)。  

```javascript:
app.use(app.router); // deprecated 
```

##### Connectのバンドル無し
- logger()等、3.xまでは始めからExpressに含まれていたConnectミドルウェアは、[別途インストール](https://github.com/senchalabs/connect#middleware)。
	
```
npm install connect
```

呼び出し方は

```javascript:
app.use(app.logger()); // ×
app.use(connect.logger()); // ◯
```

##### app.configure()が無くなった

```javascript:
app.configure('development', function() {
 	 // configure stuff here
});
// becomes
var env = process.env.NODE_ENV || 'development';
if ('development' == env) {
   	// configure stuff here
}
```

### Express 3.x
- 2014年8月現在、入手可能なほぼ全ての日本語Node.js関連書籍がExpress 3.xを解説していると思われるため、書籍を参考に勉強したい場合はExpress 3.xのインストールがおすすめ

####インストール

```
npm install -g express@3
```

#### 使用方法
- [公式ガイドを参考に](http://hideyukisaito.github.io/expressjs-doc_ja/guide/)  
<br>

## Connect
### Connectとは
- HTTPサーバのフレームワーク。httpモジュールのcreateServerのreq, resオブジェクトを横取りして独自の処理を実行し、次のコンポーネントに制御を渡す（あるいは応答を終了させる）ことができる。  
	
```javascript:
var connect = require('connect');
var app = connect();

app
  .use(function(req, res, next) {
  	// 処理1
  	・・・

	// 次のコンポーネントに処理を渡す
	next();
  })
  .use(function(req, res) {
	// 処理2
	・・・

	// レスポンスの終了
	res.end('Hello');
  })
  .listen(ポート番号);
```

### Expressとの関係
- Express 3.xまではConnectを標準でバンドルしてたが4.x以降は別途インストールが必要。
- stackoverflowの[このquestion](http://stackoverflow.com/questions/5284340/what-is-node-js-connect-express-and-middleware)が参考になる。  

### 組み込みmiddleware
- 便利なmiddlewareが組み込まれている。が、バンドルされなくなったmiddlewareが多いので、定期的に情報収集したほうがよさそう。
	
- 組み込まれているmiddlewareの詳細は、[Connectの公式](https://github.com/senchalabs/connect#middleware)、もしくは、少し情報が古いけど、[Connect ソースコードリーディング(6) - 組込み middleware 紹介](http://hakobera.hatenablog.com/entry/20111129/1322564463)が参考になる。

<br>

## 割と必須なモジュール
### [cookie-parser](https://github.com/expressjs/cookie-parser)
- クッキーの解析
- Connectにバンドルされなくなったので各自インストールが必要

### [method-override](https://github.com/expressjs/method-override)
- クライアントがサポートしてない場合でもPUTやDELETEを使えるようにする
- Connectにバンドルされなくなったので各自インストールが必要

### [body-parser](https://github.com/expressjs/body-parser)
- bodyの解析。JSON、x-www-form-urlencodedに対応。
- こちらもConnectにバンドルされなくなったので必要。
- **multipart/form-dataに対応しなくなったので、multipart解析には他のモジュールが必要**

### [multer](https://github.com/expressjs/multer)
- multipart/form-data解析


## その他便利モジュール
### [nodemon](https://github.com/remy/nodemon)  
"nodemon will watch the files in the directory that nodemon was started, and if they change, it will automatically restart your node application.  "

####インストール
- グローバル環境にインストール

```
npm install -g nodemon  
```
  
#### 使い方
- 下記コマンドで起動すれば、appName.jsに変更が加えられるたびに自動的にnodeが再起動する。

```
nodemon appName  
```

### [formidable](https://github.com/felixge/node-formidable)

ファイルアップロード用モジュール

#### インストール

```
npm install formidable  
```

#### 使い方
- [クラスメソッドの解説ページ](http://dev.classmethod.jp/server-side/node-formidable/)を参考にした。

### [nimble](http://caolan.github.io/nimble/)
フロー制御ツール

#### インストール

```
npm install nimble
```

#### 使い方

```javascript:
var nimble = require('nimble');
nimble.parallel([
	// パラレルに実行
	function(callback) {
		// パラレル処理1
		・・・

		callback();
	},
	function(callback) {
		// パラレル処理2
		・・・
				
		callback();
	}
], 全部のパラレル処理が終わった後に実行するcallback);

nimble.series([
	// 記述順に実行
	function(callback) {
		// 処理1
		・・・
				
		callback();
	},
	function(callback) {
		// 処理2
		・・・
				
		callback();
	}
], 全部の処理が終わった後に実行するcallback);
```

### [bcrypt](https://github.com/ncb000gt/node.bcrypt.js)

パスワードの暗号化

#### インストール

```
npm install bcrypt
```

#### 使い方
- 下記の記事を参考にした
	- [bcrypt](https://github.com/ncb000gt/node.bcrypt.js/blob/master/README.md)
	- [Node.jsでbcrypt](http://yuribossa.hatenablog.com/entry/20110929/p1)

<br>
## とっかかりに良かった教材  
- [Nodeビギナーズブック](http://www.nodebeginner.org/index-jp.html)

## 気になる教材
- [Node.js、Express、AngularJS、および MongoDB を使用してリアルタイム・アンケート・アプリケーションを作成する](http://www.ibm.com/developerworks/jp/web/library/wa-nodejs-polling-app/?cmp=dw&cpb=dwwdv&ct=dwrss&cr=dwrss&ccy=jp&csr=062714)