WebSocketをNode.js(Express 4 + EJS + Socket.IO)で復習がてら実装しました。
ハマりポイントはbin/www
を修正しないと動いてくれないところ。
Expressってシンプルで綺麗な設計のフレームワークなんですが、
結構はまりやすいポイントが多いと思います。
Nodeおよびライブラリのバージョン
Node.js 12.14.1
Express 4.16.1
socket.io 2.3.0
EJS 2.6.0
最終成果物
次のと同じものを作る手順を記載します。
ひな形を作成
まずexpress-generator
をグローバルインストールをします。
$ npm install express-generator -g
次にひな形生成をします。いわゆるスキャフォールディングです。
プロジェクトのフォルダはexpress-ws-ejsとします。
テンプレートはEJSを選択します
$ cd express-ws-ejs
$ express --ejs
ソースコードを修正
まずsocket.ioを使えるようにします。
$ npm i socket.io --save
$ npm i
/models/chat.js
WebSocketのサーバ側です。
新規作成します。modelsフォルダを作り、chat.jsを作成します。
const socketio = require('socket.io');
function chat(server) {
const sio = socketio.listen(server);
sio.on('connection', function(socket) {
socket.on('chat-message', function(msg) {
console.log('Send message to client');
sio.emit('chat-message', msg + '💛');
});
socket.on("disconnect", function() {
});
});
};
module.exports = chat;
■補足
いくつかあるemitの違い
const sio = socketio.listen(server);
sio.on('connection', function(socket) {
socket.emit('chat-message', 'message');
socket.broadcast.emit('chat-message', 'message');
sio.emit('chat-message', 'message');
}
他にも似たようなのがありますが、これだけ押さえておけばよいでしょう。
javascript - Send response to all clients except sender - Stack Overflow
/bin/www
ここでsocket.ioのlistenをしている/models/chat.jsを呼ばないといけません。
chat.jsはのちほど作成します。
app.jsでこれを呼ぶことはできません。というのもcreateServerをしているのが
/bin/wwwだからだと思われます。
ちなみにですが、var
じゃなくてconst
がいいのですがexpress-generator
がvar
で作るので、
var
のままにしていたりします。
@@ -5,7 +5,8 @@
*/
var app = require('../app');
-var debug = require('debug')('express-ws-ejs-o:server');
+var chat = require('../models/chat');
+var debug = require('debug')('express-ws-ejs:server');
var http = require('http');
/**
@@ -28,6 +29,7 @@
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
+chat(server);
/app.js
usersのrouterはいらないので消します
@@ -5,7 +5,6 @@
var logger = require('morgan');
var indexRouter = require('./routes/index');
-var usersRouter = require('./routes/users');
var app = express();
@@ -20,7 +19,6 @@
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
-app.use('/users', usersRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
/controllers/index.js
これは新規作成します。controllersフォルダを作り、index.jsを作成します。
exports.index = function(req, res) {
res.render('index', { title: 'Express' });
}
/routes/index.js
var express = require('express');
var router = express.Router();
var index_controller = require('../controllers/index');
router.get('/', index_controller.index);
module.exports = router;
その他リソースおよびview
主にクライアント側です。
Node使ってるとクライアント側なのかサーバ側なのかたまに混乱します。
/public/javascripts/index.js
$(function() {
const socket = io('http://localhost:3000');
$('form').submit(function() {
console.log($('#m').val());
socket.emit('chat-message', $('#m').val());
$('#m').val('');
return false;
});
socket.on('chat-message', function(msg) {
$('#messages').append($('<li>').text(msg));
window.scrollTo(0, document.body.scrollHeight);
});
});
/public/stylesheets/index.css
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font: 13px Helvetica, Arial; }
form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; }
form input { border: 0; padding: 10px; width: 90%; margin-right: .5%; }
form button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; }
#messages { list-style-type: none; margin: 0; padding: 0; }
#messages li { padding: 5px 10px; }
#messages li:nth-child(odd) { background: #eee; }
#messages { margin-bottom: 40px }
/views/index.js
@@ -2,10 +2,18 @@
<html>
<head>
<title><%= title %></title>
- <link rel='stylesheet' href='/stylesheets/style.css' />
+ <link rel='stylesheet' href='/stylesheets/index.css' />
</head>
<body>
- <h1><%= title %></h1>
- <p>Welcome to <%= title %></p>
+ <ul id="messages"></ul>
+ <form>
+ <input id="m" autocomplete="off">
+ <button type="submit">Send</button>
+ </form>
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.3.0/socket.io.js"></script>
+ <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"
+ integrity="sha256-pasqAKBDmFT4eHoN2ndd6lN370kFiGUFyTiUHWhU7k8="
+ crossorigin="anonymous"></script>
+ <script src="javascripts/index.js"></script>
</body>
</html>
Expressの起動
最後にExpressを起動すれば終わりです。
$ npm start
http://localhost:3000
にアクセスし、ブラウザのウィンドウを2つ以上立ち上げると動作確認ができます。
参考
https://socket.io/get-started/chat/
https://liginc.co.jp/web/programming/node-js/132081
https://developer.mozilla.org/ja/docs/Learn/Server-side/Express_Nodejs
https://www.gitignore.io/api/node