Node.js + Express入門

簡単なWebアプリを作る機会があったので、Node.js + Express入門してみた。

# Node.jsとnpmインストール
nodebrewを入れる。

```
$ curl -L git.io/nodebrew | perl - setup
```

.bash_profile等にパスを追加

```
export PATH=$HOME/.nodebrew/current/bin:$PATH
```

```
$ nodebrew -v
nodebrew 0.9.6
```

```
$ nodebrew ls
v4.6.2
v6.9.1
v7.1.0

current: nonde
$ nodebrew use v6.9.1
$ nodebrew ls
v4.6.2
v6.9.1
v7.1.0

current: v6.9.1
$ npm -v
3.10.8
```

# Expressインストール
npmで簡単に導入

```
$ npm install -g express
```

ただ、プロジェクト作るときにはexpress-generatorがあるとより簡単なのでこれも入れる

```
$ npm install -g express-generator
```

# Expressプロジェクトを作成
express-generatorによりプロジェクトが生成される。
使い方はrailsのgenerateと似たような感じ。
テンプレートエンジンをjadeにしたい場合は、warningで--view=jadeを指定するように怒られているが今回はそのままスルー。将来的にデフォルトでなくなるらしい。

```
$ express sampleapp

  warning: the default view engine will not be jade in future releases
  warning: use `--view=jade' or `--help' for additional options


   create : sampleapp
   create : sampleapp/package.json
   create : sampleapp/app.js
   create : sampleapp/public
   create : sampleapp/public/javascripts
   create : sampleapp/public/images
   create : sampleapp/routes
   create : sampleapp/routes/index.js
   create : sampleapp/routes/users.js
   create : sampleapp/public/stylesheets
   create : sampleapp/public/stylesheets/style.css
   create : sampleapp/views
   create : sampleapp/views/index.jade
   create : sampleapp/views/layout.jade
   create : sampleapp/views/error.jade
   create : sampleapp/bin
   create : sampleapp/bin/www

   install dependencies:
     $ cd sampleapp && npm install

   run the app:
     $ DEBUG=sampleapp:* npm start
```

依存モジュールのインストール

```
$ npm install
```

# 立ち上げてみる
Expressを起動してブラウザでアクセス(localhost:3000)

```
$ npm start
又は
$ node bin/www
```

構築完了。

<img width="1285" alt="Screen Shot 2016-12-07 at 11.14.39 AM.png" src="https://qiita-image-store.s3.amazonaws.com/0/29379/6e267d6e-c692-934d-12d2-26a33e1b6bd6.png">

# もう少し細かく見てみる
## app.jsとrouting
ここにアプリケーションに関する記述が入っている。

```js
var index = require('./routes/index');
var users = require('./routes/users');
...
app.use('/', index);
app.use('/users', users);
```

このような記述があり、以下のように動く。
URLでdocument root ('/')にアクセスした時には、routes/index.jsが読み込まれそこに記述した処理が適用される。
routes/index.jsを見てみると以下のようになっており、GETが定義されている。

```js
/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index', { title: 'Express' });
});
```

たとえばここに以下のように変えた場合、/hogehogeでアクセス出来る。


```js
/* GET home page. */
router.get('/hogehoge', function(req, res, next) {
  res.render('index', { title: 'Express' });
});
```

また、app.useの部分を以下のように変えると、違うパスにマウントされる感じで用意に切り替えることができるらしい。
こうすると、/hoge/hogehogeというパスでアクセスできるようになる。

```js
var index = require('./routes/index');
var users = require('./routes/users');
...
// app.use('/', index); 以下のように変えてみる
app.use('/hoge', index);
app.use('/users', users);
```

app.useの他にも、app.getやapp.postで直接パスを指定できるが、拡張性などを考えるとapp.useとするのが便利そう。

## npm foreverを使ってデーモン化
node bin/wwwの起動だと、コマンド終了するとサーバも停止してしまうため、[forever](https://www.npmjs.com/package/forever)というものを使ってみる。

インストール

```
$ npm install forever -g
```

foreverを使って起動する

```
$ forever start bin/www
warn:    --minUptime not set. Defaulting to: 1000ms
warn:    --spinSleepTime not set. Your script will exit if it does not stay up for at least 1000ms
info:    Forever processing file: bin/www
$
```

この起動の場合は、ログファイル名は起動毎に変わり```~/.forever/xxx.log```に出力される。

ログファイル名を指定する場合はオプションを付けて以下のようにする。

```
$ forever start -a -l app.log -e error.log bin/www
```

※-aを付けないと、次回起動時に下記のように怒られる

```
error:   Cannot start forever
error:   log file /xxxxxx/.forever/app.log exists. Use the -a or --append option to append log.
```

起動後の確認

```
$ forever list
info:    Forever processes running
data:        uid  command                                          script  forever pid   id logfile                             uptime
data:    [0] FRen /Users/xxxxxx/.nodebrew/node/v6.9.1/bin/node bin/www 61131   61132    /Users/xxxxxx/.forever/FRen.log 0:0:0:18.592
$
```

プロセスが起動しているのが分かる。
停止するときは、

```
$ forever stop bin/www
info:    Forever stopped process:
    uid  command                                          script  forever pid   id logfile                             uptime
[0] FRen /Users/xxxxxx/.nodebrew/node/v6.9.1/bin/node bin/www 61131   61132    /Users/xxxxxx/.forever/FRen.log 0:0:1:42.953
```

## 環境の切り替え
起動時にNODE_ENVを指定することで、環境ごとの設定をする。

```
$ NODE_ENV=development forever start bin/www // 開発
$ NODE_ENV=stage forever start bin/www // ステージング
$ NODE_ENV=production forever start bin/www // 本番
```

あとはconfigのymlかなんかを作って、ENVを読み込めるようにする。
以下はdatabase接続を環境ごとに分ける例。

```yaml:config/config.yml
env:
  development:
    database:
      host: localhost
      port: 5432
      user: localuser
      password: localpass

  stage:
    database:
      host: xxx.xxx.xx.xxx // DBサーバのIP
      port: 5432
      user: user1
      password: xxxxx

  production:
    database:
      host: yyy.yyy.yy.yyy // DBサーバのIP
      port: 5432
      user: user1
      password: yyyyy
```

```js:config/config.js
'use strict'

var jsYaml = require('js-yaml')
  , fs = require('fs')
  , yml = jsYaml.safeLoad(fs.readFileSync(__dirname + '/config.yml', 'utf8'))
  ;

exports.getEnvConfig = getEnvConfig;

function getEnvConfig() {
  var currentEnv = process.env.NODE_ENV || 'production' // ここで起動時に設定したものを読み込む
    ;

  return yml.env[currentEnv];
}
```

使う側の例

```js
'use strict'

var options = {}
  , config = require('../config/config')
  , dbConfig = config.getConfig()['database']
  , pgp = require("pg-promise")(options)
  , connection = {}
  , db = null
  ;

connection = {
    host: dbConfig.host,
    port: dbConfig.port,
    database: 'db_name',
    user: dbConfig.user,
    password: dbConfig.password
};
db = pgp(connection);

module.exports = db;
```