Node.jsとSocket.ioで簡易的なチャットを実現させる

# 簡易的なWebチャットを実装する
## はじめに
この記事は[SLP KBIT Advent Calender 2019](https://adventar.org/calendars/4214)の16日目の記事である。
Socket.ioを用いた開発をまだやったことがなかったので今回はそういった開発を行っていきたいと思います。
かなり前に作ったので実装過程をちょっと忘れてしまいました…。

##環境
・Windows 10(64bit)
・Node.js : v10.15.3

##準備
この開発ではNode.js、Socket.ioの他に、ローカルサーバーを簡単に立ち上げれるExpressを使うのでもしインストールしていない人は以下のコマンドでインストールしてみましょう。

```
$ npm install express
```

#実装
##サーバをたてる準備

```js:create.js
var express = require('express');//expressを使用
var app = express();
var http = require('http').Server(app);

const path = require('path');
const io = require('socket.io')(http);
const PORT = process.env.PORT || 4649;

app.get('/' , function(req, res){
    res.sendFile(__dirname+'/chat_room/chat.html');//chat.htmlへ移動
});



io.on('connection',function(socket){
     // メッセージ送信処理
    socket.on('chat message', function(msg, user){
    //io.emit('chat message', msg);
    io.emit('chat message', {
        userName: user,
        message: msg
    });

  });
});

http.listen(PORT, function(){
    console.log('server listening. Port(・v・)/:' + PORT);//PORT番ポートに接続
});

app.use(express.static(path.join(__dirname, 'chat_room')));//chat_roomディレクトリを公開
```

ちなみにchat_roomディレクトリにチャットを表示するhtmlとcssファイルを用意しているので最後の行で

```
app.use(express.static(path.join(__dirname, 'chat_room')));
```
と記述しています。(これがないとchat_roomの中にあるcssを読み込んでくれなかった)

##HTMLとCSS
チャットを表示するためのHTMLとCSSを作ります

```html:chat.html
<!DOCTYPE html>
<html>
    <head> 
      <meta http-equiv="content-type" content="text/html charset=UTF-8">
        <title>Socketテスト</title>
        <link rel="stylesheet" type="text/css" href="./style.css" />

  </head>
  <body>
<h1>チャットテスト(・v・)/</h1>

<!-- メッセージ入力欄 -->
<form action="#" id="chatForm">
    <input id="u" autocomplete="off" placeholder="ユーザ名"/>
    <input id="m" autocomplete="off" placeholder="テキスト"/>
    <button>Send</button>
</form>
<hr>

<!-- メッセージの表示 -->
<ul id="messages"></ul>

<!--必須モジュール２つ-->
<script src="/socket.io/socket.io.js"></script>
<script src="https://code.jquery.com/jquery-1.11.1.js"></script>
<script>
  var socket = io();
  //var userName = 'test';
  $(function () {
var userName = '';
    // メッセージを送信する
    $('form').submit(function(){
      socket.emit('chat message', $('#m').val(), $('#u').val());
      $('#m').val('');
      return false;
    });

    // 受信したメッセージを表示
    // ul id ="messages"の部分
    socket.on('chat message', function(data){
      var chat = data.userName + " 『 " + data.message + " 』";
      if ((data.message != '') && (data.userName != '') ) {//空じゃない場合
      $('#messages').append($('<p id="chat">').text(chat));//ユーザとテキストは前提条件
      }
    });
  });
</script>

</body>
</html>
```

```css:style.css
#messages {
    padding: 0.5em 1em;
    margin: 2em 0;
    border: solid 3px #9facd4;

}

#chat {
    margin-top: 1px;
    padding: 2px;
    background-color: rgb(218, 246, 255);
    color: #292929;
}
```

##実際に使ってみる
nodeコマンドでサーバを立ち上げます。
![ad1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309108/8de82418-2f27-3ab3-71ef-ca581453ede3.png)

ローカルホストで指定したポートにアクセスすると以下のような画面が出ます。

![ad2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309108/8e6ab80a-f615-7a3a-dfb4-cc3b62806479.png)

ユーザ名とテキストを入力してsendを押すと
![ad3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309108/ebee1664-7d65-5310-3ebf-36e404ad4190.png)

![ad4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309108/0fd4cd6d-e24f-bc93-4541-178bf7d8d801.png)
きちんとセリフっぽくなりましたね！

###ウインドウを２つ以上開いた場合
・送信前
![ad5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309108/01fc47c1-cf0b-f441-6c65-25ce3d825979.png)
・送信後
![ad6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309108/934bc268-684c-2b8c-cd88-94ce22381835.png)
片方が送信すると両方のウインドウに反映されましたね。
これでローカル環境でチャットが出来そうです。

#おわりに
チャット機能の実装だけを目標にしていたので見た目がシンプルになってしまいましたが最後まできちんとやりきることができてよかったです。アイコンを実装したりもう少し見た目をよくすると本格的なチャットが楽しめるかなと思います。