dev.kokushin

HTML5、CSS3、JavaScriptを中心に、日々のプログラミングで得た知識をメモしています。

Node.js + Socket.ioでチャットアプリをつくってみるメモ

f:id:kokushin:20160413125105j:plain

忘れないうちに「Socket.io」の使い方をメモ。
リアルタイム通信ができるので、ゲームやチャットアプリなどに使えそうですね。

今回は「Socket.io」を使用して簡易的なチャットアプリを実装してみました。

Expressインストール

せっかくなので覚えたてのExpressを無駄に利用していくスタイル

$ express chatapp -e

からの

$ npm install

以上。

不要なファイルやディレクトリを削除

EJSとかインストールしたけど別に使わなくていいので削除
routerも使わないので削除

ココらへんでExpressが全く必要がないことに気づくw

chatapp/
  ├ app.js
  ├ htdocs/
  │  ├ css/
  │  ├ index.html
  │  └ js/
  └ package.json

app.jsはhtdocsディレクトリ内のファイルをインクルードしてくるように設定。

ついでにpackage.jsonを開いて

"scripts": {
    "start": "node app.js"
  },

を設定しておく。
これで

$ npm start

でサーバーが立ち上がるようになる。

Socket.io のインストール

$ npm install socket.io --save-dev

XSS対策に node-xss-filters をインストール

チャットアプリなのでXSS攻撃されることも想定内。
これを使えば文字列をエスケープ処理して出力くれるっぽい。

$ npm install xss-filters --save-dev

app.js(サーバー)

// Expressを読み込む
var express = require('express');
var app = express();

// サーバーを構築
var http = require('http').Server(app);

// Socket.ioを読み込み、サーバーと紐付け
var io = require('socket.io')(http);

// xss-filtersも読み込んでおく
var xssFilters = require('xss-filters');

// Expressでhtmlファイルが扱えるようにパスを設定
app.use(express.static('htdocs'));

// Socket.ioの設定を書く
// Socket.ioが接続された場合に実行
io.on('connection', function(socket) {

  // クライアントから受け取ったメッセージをサーバーで処理するようイベントを登録
  // (c2s→client to server | s2c→server to client)
  socket.on('c2s_message', function(msg) {

    // メッセージが空だった場合の処理
    if (msg == '') {
      return;
    }

    // このへんにDBへ登録するなどサーバー側の処理を書く

    // サーバーで処理したメッセージをクライアントへ返す(ここでxss-filtersでエスケープ処理)
    io.sockets.emit('s2c_message', xssFilters.inHTMLData(msg));

    // メッセージログをコンソールに出力
    console.log('Say: ' + msg); 
  });
});

// サーバーの設定
var port = process.env.PORT || 3000;
http.listen(port, function() {
  console.log('Server Running.');
});

emitがデータをクライアントへ渡すときに使われるメソッド。

HTML(クライアント)

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
  <title>chatapp</title>
  <link rel="stylesheet" href="//fonts.googleapis.com/css?family=Roboto">
  <link rel="stylesheet" href="////maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
  <link rel="stylesheet" href="css/style.css">
</head>
<body>

  <form>
    <input id="chatapp-textarea" type="text" placeholder="タップでメッセージを入力">
    <button id="chatapp-submit"><i class="fa fa-send"></i></button>
  </form>

  <div id="chatapp-view"></div>

  <script src="//code.jquery.com/jquery-2.2.2.min.js"></script>
  <script src="//cdn.socket.io/socket.io-1.4.5.js"></script>
  <script src="js/app.js"></script>
</body>
</html>

jQuery、クライアント用のsocket.io.jsを読み込み。
クライアント用のJSファイルは外部化しておく。

ちなみにExpressでガッツリ実装する際は/socket.io/socket.io.jsにjsファイルが準備されるのでこれを使用する。

JavaScript(クライアント)

(function($) {

  'use strict';

  var Main = function() {
    this.$el = {
      textarea: $('#chatapp-textarea'),
      submit: $('#chatapp-submit'),
      view: $('#chatapp-view')
    };

    this._init();
  };

  Main.prototype._init = function() {
    this.initSocketio();
  };

  Main.prototype.initSocketio = function() {
    var self = this;

    // Socket.io実行
    var socket = io();

    var msg;

    // 投稿ボタンを押したら
    this.$el.submit.on('click', function(e) {
      e.preventDefault();

      // 入力されたメッセージを取得
      msg = self.$el.textarea.val();

      // サーバーへメッセージを渡す
      socket.emit('c2s_message', msg);

      // 入力欄を初期化
      self.$el.textarea.val('');
    });

    // サーバーから返ってきたメッセージを整形してメッセージビューエリアに出力
    socket.on('s2c_message', function(msg) {
      self.$el.view.prepend('<p>' + msg + '</p>');
    });

  };

  $(function() {
    new Main();
  });

})(jQuery);

実際のデモ

https://node-chatapptest.herokuapp.com/

感想とか

ここまで簡単にチャットアプリもどきが作れてしまうのか!と驚きました。
後はメッセージをDBに保存させて履歴を残し、ユーザー機能を追加して、画像やスタンプも送れるようにして、WebRTCで通話もできるようにすれば... (・∀・)ニヤニヤ