アインシュタインの電話番号
2011.06.19
HerokuでNode.jsとExpressを使ってHello worldする

普段自分はHeroku+Sinatra+Slim+SassでWebアプリを作っているんだけど、Node.jsやCoffeeScriptについてちょっと調べてたら、Herokuを使う前提で、Node.js(Express), Jade, Sassという組み合わせでCoffeeScriptで書けば、前述のSinatraアプリとほぼ同じような感覚で書けそうなことに気づいて、ぐっとNode.jsに興味が沸いた。

ということで、さっそくHerokuを使ってNode.jsアプリを作ってHello worldしてみた。今回の記事を最後まで行くと、これが出来上がる。ソースコードはGitHubに。

各種インストール

この記事ではNode.jsとExpressだけを使ってHello worldする。今回はJadeやSass, CoffeScriptは出てこない。まず、Node.jsとExpressを使うのに必要なものをインストールする。あと、今回の手順はMac環境でやっていて、Windows環境では試していない。いずれ試すつもりではいるけど、もしWindows環境でうまくいった人がいれば教えてもらえると嬉しいです。

Node.jsのインストール

Node.jsは、以前Powを使うためにインストールしたので既に入ってた。

PowをSinatraアプリで使う

上記の方法でインストールした状態のままで、バージョンは0.4.5だった。

$ node -v
v0.4.5

npmのインストール

npmはNode.js関連のパッケージマネージャで、RubyでいうRubyGemsだと思うたぶん。以下のコマンドでインストールする。

$ sudo curl [http://npmjs.org/install.sh](http://npmjs.org/install.sh) | sh

途中でYes/Noと聞かれるので、Yesと答えたらなんか色々削除された。正常にインストールされれば、npmコマンドが利用可能になる。バージョンは1.0.13だった。

$ npm -v
1.0.13

expressのインストール

んで、expressをインストールする。RubyでいうSinatraに相当する。というか、Sinatraに影響を受けたフレームワーク。npmコマンドを使うと、パッケージはプロジェクトフォルダごとにインストールされるっぽい(?)ので、まずnode-hello-worldフォルダを作って、そこでインストールコマンドを実行する。バージョンは2.3.11だった。

$ mkdir node-hello-world
$ cd node-hello-world
$ npm install express .
express@2.3.11 ./node_modules/express 
├── mime@1.2.2
├── connect@1.4.5
└── qs@0.1.0

各種ファイルの作成

Node.jsアプリを構成する上で必要な各種ファイルを作成する。

web.js

まずメインのコードとなるweb.jsを作る。Sinatraアプリで言うapp.rbに相当する。

var express = require('express');

var app = express.createServer();

app.get('/', function(req, res) {
    res.send('HerokuでNode.jsとExpressを使ってHello world!');
});

var port = process.env.PORT || 3000;
app.listen(port, function(){
  console.log("Listening on " + port);
});

package.json

次にNode.jsアプリの情報や使用するパッケージの情報を記述するpackage.jsonを記述する。Sinatraアプリで言うGemfileに相当しそうだけど、アプリ自体の情報も含んでいるのでちょっと違うかな?

{
  "name": "node-hello-world",
  "version": "0.0.1",
  "dependencies": {
    "express": "2.3.11"
  }
}

Procfile

次に新Heroku環境(新スタック)であるCedarから採用されたProcfileを作成する。これは今までのHerokuアプリには無かったもので、Herokuアプリの動作方法(プロセスモデル)を指定するもの。web, worker, clockの3種類があるんだけど、webが今までのWebアプリで、他の2つはよくわからない。今回はWebアプリを作っているのでwebを指定するProcfileを作成する。

web: node web.js

.gitignore

最後に.gitignoreを作る。先ほどexpressをプロジェクトディレクトリ直下のnode_modulesフォルダにインストールしたので、これをコミットに含めないように指定しておく。

node_modules

以上の4ファイルが作成できれば準備は完了。

.
├── .gitignore
├── Procfile
├── package.json
└── web.js

ローカルプレビュー

上述の4ファイル+パッケージ(node_modulesフォルダ)で作ったNode.jsアプリをローカルでプレビューするには、nodeコマンドを使って、

$ node web.js
Listening on 3000

として、http://localhost:3000/にアクセスする。もしくは、Procfileファイル経由で起動する場合はforemanというgemを使うとできる。$ foreman startすると、Procfileの中身を参照してアプリを起動してくれる。

$ gem install foreman
$ foreman start
01:06:59 web.1     | started with pid 3756
01:06:59 web.1     | Listening on 5000

上述のとおり5000番ポートで起動しているので、http://localhost:5000/にアクセスすると「HerokuでNode.jsとExpressを使ってHello world!」と表示されるはず。上記どちらかの方法で、Node.jsアプリの動作が確認できたら、Ctrl+CでNode.jsアプリを終了する。

Herokuへデプロイ

最後にHerokuへデプロイするけど、従来のようにHerokuアプリを新規作成してはNode.jsを動かすことはできないので注意。 新しいStackで作る必要がある。さらに、heroku gemのバージョンが古いと新しいStackのHerokuアプリを新規作成できないので要注意。 これでちょっとハマった。まずはheroku gemのアップデートをしておこう。

$ gem update heroku
$ gem list heroku
###  LOCAL GEMS ***

heroku (2.3.3)

gemをアップデートしたら、新しいCedarスタックでHerokuアプリを新規作成する。

$ heroku create node-hello-world --stack cedar
Creating node-hello-world... done, stack is cedar
[http://node-hello-world.herokuapp.com/](http://node-hello-world.herokuapp.com/) | git@heroku.com:node-hello-world.git

このように--stack cedarと新しいStackを指定して作成する必要があり、Cedarスタックを指定して作ったHerokuアプリは、従来の「アプリ名.heroku.com」というドメインではなく、「アプリ名.herokuapp.com」で作成される。heroku.comとherokuapp.comの違いはここに書いてあるっぽいけど英語よくわからん。良くなってる感はなんとなく伝わってくる。以降の部分は、従来のデプロイと同じ手順。

$ git add .
$ git commit -m 'first commit'
$ git push heroku master
$ heroku open

これでデプロイが完了。http://node-hello-world.herokuapp.com/を開けば「HerokuでNode.jsとExpressを使ってHello world!」と表示されているはず。ここまでのソースコード一式をGitHubに置いた。

ruedap/node-hello-world at 0.0.1 - GitHub

まとめ

まだHello worldしただけなので、どうこう言えるレベルではないのだけど、Herokuへデプロイするまでの流れは、今までのSinatraアプリと大差なく行えた。あとはコーディング周りでRuby+Sinatraの簡単さ・簡潔さをどれだけCoffeScript+Node.jsで実現できるか、が自分にとっては重要なので、これから触って試してみたい。

ただ、1点困ってるのが「Node.js使うと何が嬉しいの?」が自分の中で明確になっていないので、使うモチベーションがあがらない。よく聞く「リアルタイムやプッシュ型のWebアプリに適している」「JavaScriptで書ける」などは自分には今のところ大きなメリットにはなっておらず、 ふつーのWebアプリを、Ruby+Sinatraで作るときに比べて、メリットは何か? がわからなくてモヤモヤしてる感じ。これが見つけられると、グッと傾きそうな予感がしないでもない。逆に言えば、これが無い限りは、今まで通り使い慣れたRuby+Sinatraで作ったほうが効率が良いということになりそう。

追記

はてブのコメント欄で教えていただいた@hide_o_55さんのNode.jsメリット・デメリットの記事がわかりやすかった。

Node.jsの使いどころ - WebService::Blog->new( user => ’hide_o_55’ )

現状はやはり、リアルタイムやプッシュ型のWebアプリを作成するのに適していて、無理に利用するものではないし、今すぐ既存の技術をリプレースするものでは無い模様。念の為に言っておくと、Node.jsを否定しているわけじゃなく、すごく賑わっていて注目されてて気になっているんだけど、それを使った場合の自分の中でのメリットをちゃんと把握できてない、ってだけの話なので誤解なきよう。

ノンブロッキングI/Oと言われてもしっくりこない人は多いんじゃないかな? 今の自分がそう。色々な記事を読んだりして、どういう場面で使えるか? 自分が使っている今の技術に比べてどんな利点があるか? を調べている段階。中でも以下の2つの記事はとてもわかりやすかった。

node.js とは何か - I am Bad at Math Node.jsとは何か、開発者ライアン・ダール氏が語る(前編)~ノンブロッキングとはどういうことか? - Publickey


Express - node Webフレームワーク | 日本語ドキュメンテーション Heroku + Node.js + ExpressでHelloWorldを書いてみた。 | EIPラボ Heroku | Dev Center | Getting started with Node.js on Heroku/Cedar