23.
簡易チャットアプリ
Chatプロジェクト
ExpressとSocket.ioを利用して、簡易チャットアプリを作成します。
ファイル構成
node_chat/
├── package-lock.json
├── package.json
├── public/
│ ├── js
│ │ └── chat.js
│ └── index.html
└── server.js
プロジェクト作成
初期化
「node_chat」プロジェクトを作成し、Node.jsで初期化します。
npm init -y
モジュールインストール
必要なモジュールをインストールします。
npm i socket.io express dotenv nodemon
- socket.io
- express
- dotenv
- nodemon
.env 作成
.env ファイルを作成し、サーバーのホストとポートを設定します。
.env
HOST=localhost
PORT=3000
スクリプト登録
Node Monitorで起動
「package.json」で、nodemon server を起動するスクリプトを登録します。
package.json
...
"scripts": {
"dev": "nodemon server",
"test": "echo \"Error: no test specified\" && exit 1"
},
...
サーバサイド
Express
「server.js」でExpressを作成し、マルチバイト対応とWebルート「pulblic/」を公開します。
server.js
const express = require('express')
const app = express()
app.use(express.urlencoded({ extended: true }));
app.use(express.static(__dirname + '/public'));
HTTPサーバー
createServerモジュールを読み込み、HTTPサーバーを作成します。
server.js
const { createServer } = require('node:http');
const server = createServer(app);
環境変数読み込み
「.env」から、ホストとポートを読み込みます。
server.js
const dotenv = require('dotenv');
dotenv.config();
const host = process.env.HOST
const port = process.env.PORT
サーバ待機
HTTPサーバを待機します。
server.js
server.listen(port, host, () => {
console.log(`listening on http://${host}:${port}`);
})

Socket.io
Socket.io サーバーを作成し、io オブジェクトでWebSocket通信します。
server.js
// Socket.ioモジュール読み込み
const { Server } = require('socket.io');
// Socket.ioサーバー作成
const io = new Server(server);
connectイベント
クライアントからの接続は、connectイベントで設定します。 接続が確立すると、socket.id がクライアントIDとして取得できます。
server.js
io.on('connection', (socket) => {
//Socket.io のクライアントID
console.log('connected:' + socket.id);
})
メッセージ受信
socket.on() でデータ受信します。イベント名は「chat_message」とします。
server.js
io.on('connection', (socket) => {
console.log('connected:' + socket.id);
socket.on('chat_message', (data) => {
console.log(data);
})
})
メッセージ送信
io.emit() で接続中のすべてのクライントにメッセージ送信します。 イベント名は「chat_message」とします。
server.js
io.on('connection', (socket) => {
console.log('connected:' + socket.id);
socket.on('chat_message', (data) => {
console.log(data);
//メッセージ送信
io.emit('chat_message', data);
})
})
サーバ起動
サーバプログラムを起動します。
ターミナル
npm run dev
動作確認
http://localhost:3000 にアクセスして、HTTPサーバを確認してみましょう。

クライアント
Chatクライアントを作成し、WebSocket でメッセージを送受信します。
クライアントファイル作成
「public/」にクライアントファイルを作成します。
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Chat</title>
<!-- Bootstrap5 CDN -->
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
rel="stylesheet">
</head>
<body>
</body>
</html>
Socket.ioインストール
headタグで、クライアント用のSocket.ioライブラリを読み込みます。
public/index.html
<head>
<meta charset="UTF-8">
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<!-- Socket.io -->
<script type="text/javascript" src="/socket.io/socket.io.js"></script>
</head>
メインコンテンツ
メッセージ送信フォームとチャット一覧の領域を作成します。
public/index.html
...
<body>
<div class="container">
<h3 class="h3">Chat</h3>
<div class="form-group">
<textarea class="form-control mt-3 mb-3" id="message" placeholder="Message"></textarea>
<button onclick="sendMessage()" class="btn btn-sm btn-primary">Send</button>
</div>
<h3 class="h3">Message</h3>
<div id="chatList"></div>
</div>
<script type="text/javascript" src="js/chat.js"></script>
</body>
...
メインプログラム
Chatのメインプログラム「js/chat.js」を読み込みます。
サーバ接続
io.connect() メソッドにURL指定して、Socket.io でサーバ接続します。
chat.js
const URL = '';
const socket = io.connect(URL);
- 今回は、HTTPとWebsocketは同じサーバのため、URLは空欄とします。
データ送信イベント
socket.emit() でクライアントからサーバにデータを送信します。イベント名はサーバの socket.on() とあわせます。
socket.emit(イベント名, データ);
emit() でサーバにメッセージ送信します。イベント名は chat_message とします。
chat.js
const URL = '';
const socket = io.connect(URL);
function sendMessage() {
// Textareaのメッセージ取得
var message = document.getElementById('message').value;
console.log(message);
// chatサーバの「chat_message」メッセージ送信
socket.emit('chat_message', {
message: message,
})
}
データ受信イベント
socket.on() でサーバからのイベントを登録できます。 イベント名はサーバの emit() とあわせます。
socket.on(イベント名, 処理);
socket.on() でサーバ受信イベントを登録します。 イベント名はサーバで設定した message とします。
socket.on('chat_message', (data) => {
console.log('message', data)
})
メッセージ表示処理
データを受信したら HTML にメッセージを表示します。
socket.on('chat_message', (data) => {
console.log('message', data)
var chatList = document.getElementById('chatList');
var div = document.createElement('div');
var dateElement = document.createElement('span');
var userElement = document.createElement('span');
var messageElement = document.createElement('p');
dateElement.innerText = dateFormat(data.time);
dateElement.classList.add(['pe-3']);
messageElement.innerText = data.message;
userElement.innerText = data.socketID;
userElement.classList.add(['text-muted'])
div.append(dateElement);
div.append(userElement);
div.append(messageElement);
chatList.prepend(div);
});
動作確認
複数のブラウザで、チャットメッセージの送受信を確認してみましょう。
クライアントログ
クライアント側は DevTools でログが確認できます。
ソース
server.js
const express = require('express');
const app = express();
const http = require('http').createServer(app);
const io = require('socket.io')(http);
const dotenv = require('dotenv');
dotenv.config();
const host = process.env.HOST
const port = process.env.PORT
app.use(express.urlencoded({ extended: true }));
app.use(express.static(__dirname + '/public'));
http.listen(port, host, () => {
console.log(`listening on http://${host}:${port}`);
})
io.on('connection', (socket) => {
socket.on('chat_message', (data) => {
console.log(data);
data.socketID = socket.id;
data.time = Date.now();
io.emit('chat_message', data);
})
})
public/js/chat.js
const url = '';
const socket = io.connect(url);
// メッセージ受信
socket.on('chat_message', (data) => {
console.log('message', data)
var chatList = document.getElementById('chatList');
var div = document.createElement('div');
var dateElement = document.createElement('span');
var userElement = document.createElement('span');
var messageElement = document.createElement('p');
dateElement.innerText = dateFormat(data.time);
dateElement.classList.add(['pe-3']);
messageElement.innerText = data.message;
userElement.innerText = data.socketID;
userElement.classList.add(['text-muted'])
div.append(dateElement);
div.append(userElement);
div.append(messageElement);
chatList.prepend(div);
});
function sendMessage() {
var message = document.getElementById('message').value;
if (!message) return;
var data = {
message: message,
};
socket.emit('chat_message', data);
document.getElementById('message').value = "";
}
function dateFormat(time) {
var date = new Date(time);
var dateString = date.toLocaleDateString('ja-JP');
var timeString = date.toLocaleTimeString('ja-JP');
var dateFormat = `${dateString} ${timeString}`;
return dateFormat
}
public/index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script type="text/javascript" src="/socket.io/socket.io.js"></script>
</head>
<body>
<div class="container">
<h3 class="h3">Chat</h3>
<div class="form-group">
<textarea class="form-control mt-3 mb-3" id="message" placeholder="Message"></textarea>
<button onclick="sendMessage()" class="btn btn-sm btn-primary">Send</button>
</div>
<h3 class="h3">Message</h3>
<div id="chatList"></div>
</div>
<script type="text/javascript" src="js/chat.js"></script>
</body>
</html>