herokuでNode.jsを使ってchatアプリ その2

次にchatアプリケーションを作ってみましょう。
f:id:yosuke_furukawa:20110803153627p:image
一回目の説明にもあった通り、今回のアプリはほとんど@sugyanさんの下記ページから参考にしました。
node.jsでchatアプリっぽいもの作るメモ - すぎゃーんメモ

Node.jsとnpmのinstallは@sugyanさんのページを参照してください。
socket.ioのinstallの際の注意点ですが、自分の環境では、socket.ioの最新バージョンV0.7.7は動作しませんでした。
なので、socket.ioだけはこんな感じでinstallしました。
*1

npm install socket.io@0.6.18

さて、いよいよコードを書きます。
まずは本体、app.jsです。サニタイズされていないという指摘を受けたので修正しました。
/app.js

var express = require('express');
var app = express.createServer();
var ejs = require('ejs');
var io = require('socket.io');

var port = process.env.PORT || 3000;
app.configure(function() {
var expressStatic = express.static(__dirname + '/static');
app.use(expressStatic);
});
app.set('view engine', 'ejs');
app.set('view options', { layout: false });

app.set('transports', ['xhr-polling']);
app.set('polling duration', 10);
app.get('/', function(req, res) {
console.log('/');
res.render('index', { locals: { port: port } });
});
app.listen(port);

var socket = io.listen(app);
socket.on('connection', function(client) {
client.on('message', function(msg) {
console.log('send :' + msg);
var sanitized = escapeHTML(msg);
client.send(sanitized);
client.broadcast(sanitized);
});
client.on('disconnect', function() {
console.log('disconnect');
});
});
function escapeHTML(str) {
return str.replace(/&/g, "&").replace(/"/g, """).replace(//g, ">");
console.log('Server running at ' + port + '/');

表示部分の実装である、viewを作成します。
viewはejsというライブラリを利用して実現しています。
viewsの下にindex.ejsを作成してください。
/views/index.ejs

<html>
<head>
<title>Yosuke Chat test</title>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">google.load("jquery", "1.4.4");</script>
<script type="text/javascript" src="/socket.io/socket.io.js"></script>
<script type="text/javascript">var port = <%= port %>;</script>
<script type="text/javascript" src="/js/client.js"></script>
<link href="/css/style.css" rel="stylesheet" type="text/css">
</head>
<body>
<form action="" id="form">
<input type="text" name="message" id="message" />
<input type="submit" />
</form>
<hr />
<dl id="list"></dl>
</body>
</html>

最後にクライアント側の実装である、/static/js/client.jsを記載します。
/static/js/client.js

$(function() {
var socket = new io.Socket();
socket.connect();
socket.on('connect', function() {
console.log('connect');
});
socket.on('message', function(msg) {
var date = new Date();
$('#list').prepend($('<dt>' + date + '</dt><dd>' + msg + '</dd>'));
});
socket.on('disconnect', function(){
console.log('disconnect');
});

$('#form').submit(function() {
var message = $('#message');
socket.send(message.val());
message.attr('value', '');
return false;
});
});

ひとまず完成です。
herokuでnode.jsのコードを書く際の注意点ですが、portとhost名はheroku側から指定されるため、そのまま指定しない方がよいです。
具体的に言うと、下記のようなコードにしないといけません。
portの指定方法:
×ポート番号をそのまま指定しちゃだめ。

var express = require('express');
var app = express.createServer();
var port = 3000;
app.listen(port);

○ process.envにある環境変数を使いましょう。

var express = require('express');
var app = express.createServer();
var port = process.env.PORT || 3000;
app.listen(port);

socket.ioのインスタンスもportを指定しちゃだめ。
×

var socket = new io.Socket(null, { port: port });

var socket = new io.Socket();

試しに実行するだけであれば、

$ node app.js

と実行し、http://localhost:3000/にアクセスすればチャットシステムが使えると思います。

作ったアプリケーションをherokuへデプロイします。
まず、本アプリケーションの依存関係をpackage.jsonに記載します。
package.json

{
"name": "node-chat-example",
"version": "0.0.1",
"dependencies": {
"express": "2.2.0",
"socket.io": "0.6.18",
"ejs": "0.4.3"
}
}

この後で、一度

$ npm install

と実行すると、ローカルのnode_modulesに
package.jsonの依存関係がそのままインストールされます。
ただ、node_modulesの内容がheroku側にアップロードされると
不具合を招く危険性があるので、下記の.gitignoreで無視するように
設定しておきましょう。
.gitignore

node_modules

次にHerokuが実行するためのProcfileを記載します。
Procfileには、Herokuがweb processとして常駐させるために
実行するコマンドを記載します。
ここでは以下のように記載します。
Procfile

web: node app.js

次に本体を含めてファイルをいったんgitに入れておきます。

$ git init
$ git add .
$ git commit -m "my first chat system"

成功したら、herokuにアプリケーションを作成します。

$ heroku create --stack cedar

適当なURLとアプリケーション名が割り当てられますが、後から変更可能です。

最後にデプロイです。

$ git push heroku master

これでデプロイ完了です。

動作確認は下記の要領でコマンドから実行できます。
アプリケーションの生死確認

$ heroku ps

up for XXsのように出力されていれば起動しています。

ログ確認

$ heroku logs

エラーなどがなければ、実際にページにアクセスしてみてください。
ちゃんとchatシステムが起動すれば、完成です。

ちなみに僕がデプロイしたのは下記のURLになります。
Yosuke Chat test

もう少ししたら、ちゃんとDBも使って内容を保存できるようにしたいですね。
Enjoy your heroku life!

*1:これは@sugyanさんのtweetがなかったらよくわからなかったかも。@sugyanさん、ありがとうございました。
すごくタイミングが良かったです。
[https://twitter.com/#!/sugyan/status/98589954401251328]