※この記事の続きもよくご覧いただいてます。※
【Node.js】Socket.IO+MongoDBを使って保存できるチャットを作る方法

なんとかチャットを作ることができるようになりました。まだ仕組みの表面しか理解できてないかもしれませんが、入り口には立てたと思います。ただソースを落としてきて、「あー動いた。」でもいいんですが、僕は分からなくてもソースを書いていけば、そのうち理解できるかもという非効率な勉強法が好きなので、^-^; 同じ方がいらっしゃればお役に立てる内容になればと思います。

ソースコード

https://github.com/cotapon/chat-socket_io-sample

環境

  • MacOS 10.6.8
  • ターミナル.app
  • node v0.6.11 or v0.8.4 ※
  • npm v1.1.45
  • express v2.5.11
  • socket.io v0.8.7
    ※node.jsのバージョンによっては、socket.ioが繋がらないなどの現象があります。今回はv0.6.11と、2012年7月31日現在の安定版、v0.8.4でも検証して成功しました。

node.jsのバージョンを確認

まず、node.jsのバージョンを確認しましょう。

$ node -v
v0.6.11

もし、v0.6.x以下でしたら、うまくexpressとsocket.ioが繋がらない可能性がありますので、node.jsのバージョンを上げます。 参考にnvmという、node.jsのバージョン管理ツールで変更する方法をメモします。 nvmがインストールされていないかたは、こちらの記事を御覧ください。

//node.js v0.8.4をインストール
$ nvm install v0.8.4
 
//インストールしたバージョンを使います。
$ nvm ues v0.8.4
Now using node v0.8.4
 
//ターミナルを閉じても使えるようにしておく
$ nvm alias default v0.8.4
default -> v0.8.4

npmをインストールする。

※既にnpmが入ってる方は、ここの項目は飛ばして下さい。

//npmをインストール
$ curl http://npmjs.org/install.sh | sudo sh
 
//インストールされたか確認する。
$ npm -v
1.1.45

これで一応npmがインストールされました。次はexpressをインストールします。

expressをインストールする。

expressはnode.jsの雛形を生成してくれる便利なモジュールです。今回はejsというテンプレートを使いたいので、それが使えるexpressのバージョンを2.5.11に指定します。

//-gオプションを付けておきます。
$ npm install -g express@2.5.11
 
//インストールされたか確認します。
$ express -v
2.5.11

これで必要なものは揃いました。さて、次は必要なファイルを生成していきます。

expressを使ってファイルを生成

expressで雛形を作る際、テンプレートの指定をしていなかったらjadeが選択されます。ejsを使いたい場合は、オプションで-tの後にejsを指定するとインストールできます。最後に付けるのは、生成するディレクトリ名を入力します。「chat」という名前にしました。今回はejsのパターンでやってみましょう。

$ express install -t ejs chat
 
   create : chat
   create : chat/package.json
   create : chat/app.js
   create : chat/public
   create : chat/public/javascripts
   create : chat/public/images
   create : chat/public/stylesheets
   create : chat/public/stylesheets/style.css
   create : chat/routes
   create : chat/routes/index.js
   create : chat/views
   create : chat/views/layout.ejs
   create : chat/views/index.ejs
 
   dont forget to install dependencies:
   $ cd chat && npm install

ディレクトリと必要なテンプレートファイルが生成されましたね。では、最後の1行に出てきた、cdで移動して、npm install コマンドを実行します。

$ cd chat
$ npm install
 
npm WARN package.json application-name@0.0.1 No README.md file found!
npm http GET https://registry.npmjs.org/express/2.5.11
npm http GET https://registry.npmjs.org/ejs
npm http 304 https://registry.npmjs.org/ejs
npm http 304 https://registry.npmjs.org/express/2.5.11
npm http GET https://registry.npmjs.org/connect
npm http GET https://registry.npmjs.org/mime/1.2.4
npm http GET https://registry.npmjs.org/qs
npm http GET https://registry.npmjs.org/mkdirp/0.3.0
npm http 304 https://registry.npmjs.org/qs
npm http 304 https://registry.npmjs.org/mkdirp/0.3.0
npm http 304 https://registry.npmjs.org/mime/1.2.4
npm http 304 https://registry.npmjs.org/connect
npm WARN package.json connect@1.9.2 No README.md file found!
npm http GET https://registry.npmjs.org/formidable
npm http 304 https://registry.npmjs.org/formidable
ejs@0.8.0 node_modules/ejs
 
express@2.5.11 node_modules/express
├── qs@0.4.2
├── mkdirp@0.3.0
├── mime@1.2.4
└── connect@1.9.2 (formidable@1.0.11)

とりあえずできました。次はsocket.ioをインストールします。

socket.ioのインストール

socket.ioをインストールするにはnpmを使います。@0.8.7を追記することによってバージョン指定をすることができます。今回は安定版のv0.8.7を使います。

$ npm install socket.io@0.8.7
npm WARN package.json application-name@0.0.1 No README.md file found!
npm http GET https://registry.npmjs.org/socket.io
npm http 304 https://registry.npmjs.org/socket.io
npm http GET https://registry.npmjs.org/policyfile/0.0.4
npm http GET https://registry.npmjs.org/redis/0.6.7
npm http GET https://registry.npmjs.org/socket.io-client/0.8.7
npm http 304 https://registry.npmjs.org/socket.io-client/0.8.7
npm http 304 https://registry.npmjs.org/redis/0.6.7
npm http 304 https://registry.npmjs.org/policyfile/0.0.4
npm http GET https://registry.npmjs.org/xmlhttprequest/1.2.2
npm http GET https://registry.npmjs.org/uglify-js/1.0.6
npm http GET https://registry.npmjs.org/websocket-client/1.0.0
npm http 304 https://registry.npmjs.org/xmlhttprequest/1.2.2
npm http 304 https://registry.npmjs.org/uglify-js/1.0.6
npm http 304 https://registry.npmjs.org/websocket-client/1.0.0
socket.io@0.8.7 node_modules/socket.io
├── policyfile@0.0.4
├── redis@0.6.7
└── socket.io-client@0.8.7 (xmlhttprequest@1.2.2, websocket-client@1.0.0, uglify-js@1.0.6)

「node_modules」というディレクトリの中に、「socket.io」というディレクトリができてたらOKです。では、ソースコードを書いていきましょう。書く内容は、そんなに多くないです。app.jsをエディタで開いて下さい。

app.jsの編集

app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/**
 * Module dependencies.
 */
 
var express = require('express')
  , routes = require('./routes');
 
var app = module.exports = express.createServer();
 
// Configuration
 
app.configure(function(){
  app.set('views', __dirname + '/views');
  app.set('view engine', 'ejs');
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(app.router);
  app.use(express.static(__dirname + '/public'));
});
 
app.configure('development', function(){
  app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
 
app.configure('production', function(){
  app.use(express.errorHandler());
});
 
// Routes
 
app.get('/', routes.index);
 
app.listen(3000, function(){
  console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);
});
 
//※ここから追記
//socket
 
var io = require('socket.io').listen(app);
io.sockets.on('connection', function (socket) {
    //クライアント側からのイベントを受け取る。
    socket.on('msg send', function (msg) {
        //イベントを実行した方に実行する
        socket.emit('msg push', msg);
        //イベントを実行した方以外に実行する
        socket.broadcast.emit('msg push', msg);
    });
    //接続が解除された時に実行する
    socket.on('disconnect', function() {
        log('disconnected');
    });
});

ほとんどそのままで大丈夫です。一番最後の行、//socketのコメント部分から下の記述をコピペして下さい。次にフロント側のJavaScritpを追記します。

chat.jsを新規で作成。

public/javascripts の中に、「chat.js」という名前のファイルを作って、下記をコピペします。

chat.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$(function() {
    var socket = io.connect('http://localhost');
    socket.on('connect', function() {
        console.log('connected');
    });
     
    $('#btn').click(function() {
        var message = $('#message');
        console.log(message);
        //サーバーにメッセージを引数にイベントを実行する
        socket.emit('msg send', message.val());
    });
 
    //サーバーが受け取ったメッセージを返して実行する
    socket.on('msg push', function (msg) {
        console.log(msg);
        var date = new Date();
        $('#list').prepend($('<dt>' + date + '</dt><dd>' + msg + '</dd>'));
    });
     
    socket.on('msg updateDB', function(msg){
        console.log(msg);
    });
});

jQueryを使いますのでこうなりました。次は、HTML側に当たる、layout.ejsを編集します。

layout.ejsを編集

layout.ejs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE html>
<html>
  <head>
    <title><%= title %></title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script type="text/javascript" src="/socket.io/socket.io.js"></script>
    <script type="text/javascript" src="/javascripts/sample.js"></script>
  </head>
  <body>
    <input type="text" name="message" id="message" />
    <button id="btn">送信</button>
    <dl id="list"></dl>
  </body>
</html>

追記する部分は、jQueryの読み込み、socket.ioの読み込み、先ほど作ったcaht.jsを読み込みして、bodyの中に、テキスト入力とボタン、チャットのメッセージが表示される部分を追記しました。これで必要な記述は終わりました。準備するまでのほうが長かったですね。ではサーバーを起動してみます。

サーバー起動

$ node app.js
   info  - socket.io started
Express server listening on port 3000 in development mode

localhostのポート3000で開くと、チャット画面が出てると思います。 ブラウザの違うタブなどで2つ開いて、交互に入力したらチャットできてるでしょうか?

まとめ

今回はものすごく簡単なチャットWEBアプリを作る方法を紹介しました。socket.ioの機能として抑えておきたいポイントは、 アプリ側の socket.on('◯◯',function(value){}); でイベントを待機、クライアント側のJavaScript側から、 socket.emit('◯◯', value); で実行、 socket.broadcast.emit('◯◯', value); で傍観者と、この3つ抑えておけば、WEB Socketの流れをイメージしやすいかと思います。 メッセージのやり取り以外にも、canvasを使ったお絵かきチャットや、enchant.jsを使ってちょっとしたオンラインゲームができたり、このサンプルはブラウザを閉じたらメッセージは消えちゃいますが、mongoDBのmongooseを使って本格的に使えるチャットを作ることができたりします。次回は、これのどれかを作ってみたいと思います。また記事にしますので乞うご期待。