okada

Node.jsを使ってチャット

Node.jsを使ってSocket.ioを用いたチャットルームを作成したいと思います

せっかくなので、前回紹介したYeomanを使って作成

generator-socketioというジェネレータがあるようなのでコレを使います。

まずはジェネレータのインストール

XXXXX:chat XXXXX$ sudo npm install -g generator-socketio
Password:

実行するディレクトリをつくったらyoで実行

今回はbootstrap使用、スタイルシートはCSSを使うことにします

XXXXX:workspace XXXXX$ mkdir chat
XXXXX:workspace XXXXX$ cd chat
XXXXX:chat XXXXX$ yo socketio

_-----_
| |
|--(o)--| .--------------------------.
`---------´ | Welcome to Yeoman, |
( _´U`_ ) | ladies and gentlemen! |
/___A___\ '__________________________'
| ~ |
__'.___.'__
´ ` |° ´ Y `

[?] What do you want to call this project? chat
[?] Write a brief description.
[?] What port number would you like to run on? 1337
chat
to run on port - 1337
[?] Do you want to use Bootstrap? Yes
true
[?] In what format would you like the Bootstrap stylesheets? css
css
create server.js
create views/index.ejs
create public/js/app.js
create Gruntfile.js
create package.json
create bower.json
create .editorconfig
create .jshintrc
create .bowerrc
create .gitignore

~~~

あとはgruntで実行するだけ。あーなんて楽ちん…

-スクリーンショット 2014-11-24 23.15.25

XXXXX:chat XXXXX$ grunt

あーbootstrap入れてなかった

Gruntfile.jsを確認した所、public/bowser_componentsにbootstrapファイルを

入れるといいみたいですね

XXXXX:chat XXXXX$ vi Gruntfile.js
~~~
cssmin: {
combine: {
files: {
'public/css/core.css': 'public/bower_components/bootstrap.css/css/bootstrap.css'
~~~

publicにbower_componentsディレクトリを作成し、公式サイトでDLしたbootstrapファイルを入れます

-スクリーンショット 2014-11-24 11.18.45

XXXXX:public XXXXX$ mkdir bower_components/
XXXXX:public XXXXX$ mkdir bower_components/bootstrap.css/

もう一回gruntで実行

おおーうまく行った!

-スクリーンショット 2014-11-24 23.14.16

すでに基本的なチャット機能が入っているようで、

もう一つブラウザを開いて文章のやりとりをしてみるときちんと動きます

せっかくなので、少し編集を加えてチャット部屋を用意してみることにします

TOP(localhost:1337)にアクセスしたらランダムなユーザ名と部屋IDを作成し、

各部屋(localhost:1337/id)に飛ぶイメージです

以下編集後

server.js 38行目〜

/*************************************
//
// chat app
//
**************************************/

// express magic
var express = require('express');
var app = express();
var server = require('http').createServer(app)
var io = require('socket.io').listen(server);
var device = require('express-device');

var runningPortNumber = process.env.PORT;


app.configure(function(){
// I need to access everything in '/public' directly
app.use(express.static(__dirname + '/public'));

//set the view engine
app.set('view engine', 'ejs');
app.set('views', __dirname +'/views');

app.use(device.capture());
});


// logs every request
app.use(function(req, res, next){
// output every request in the array
console.log({method:req.method, url: req.url, device: req.device});

// goes onto the next function in line
next();
});

app.get("/", function(req, res){
res.redirect('/'+ random_string(12));
});

app.get('/:room', function(req, res) {
res.render('index', {room: req.params.room, name: random_string(5)});
});

io.sockets.on('connection', function (socket) {
var room; // 部屋ID
var name; // ユーザ名

socket.emit('connected');

socket.on('init', function(data) {
room = data.room;
name = data.name;

socket.join(room);
socket.broadcast.to(room).emit('blast', {msg:""+ name +" connected"});
});

socket.on('blast', function(data, fn){

console.log(data);
io.sockets.to(room).emit('blast', {msg:data.msg});

fn();//call the client back to clear out the field
});

socket.on('disconnect', function() {
socket.broadcast.to(room).emit('blast', {msg:""+ name +" disconnected"});
socket.leave(room);
});

});


server.listen(runningPortNumber);


/**
* ランダムな文字列を返す
*/
function random_string(len) {
var base = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
base = base.split('');
var str = '';
var count = base.length;
for(var i=0; iindex.ejsはnameとroomを追加しただけ

views/index.ejs 52行目〜

Send
app.jsも同じくnameとroom追加

public/js/app.js 13行目〜

// shortcut for document.ready
$(function(){
//setup some common vars
var $blastField = $('#blast'),
$allPostsTextArea = $('#allPosts'),
$clearAllPosts = $('#clearAllPosts'),
$sendBlastButton = $('#send'),
$nameField = $('#name'),
$roomField = $('#room');

socket.emit('init', {name:$nameField.val(), room:$roomField.val()});

$sendBlastButton.click(function(e){

var blast = $blastField.val();
var name = $nameField.val();
if(blast.length){
socket.emit("blast", {msg:name +': '+ blast},
function(data){
$blastField.val('');
});
}


});

ここまで編集したらもう一回grunt実行

自動的に部屋へジャンプするようになりました

-スクリーンショット 2014-11-24 22.32.44

もう一つウィンドウを開き、同じURLにアクセスした後、

元の画面で確認すると部屋に別の人が入室したことを表示してくれています

-スクリーンショット 2014-11-24 23.05.40

もちろんチャットも出来ますし

ついでに退出を知らせる機能もあります

ウィンドウを消すと"●●● disconnected"と表示されることが確認できます

-スクリーンショット 2014-11-24 23.10.16

以上。らくちん。