画面サーバ(React)とWebサーバ(Node.js)をSocket.ioで接続する方法メモ
はじめに
今回の記事の目的
画面サーバ(React)とWebサーバ(Node.js)を別々に構築して、クライアントとWebサーバ間をSocket.ioで接続する。
チャットアプリを作る事前準備になる。
参考記事
- 公式ドキュメントのクライアントサイドの設定方法。Reactでのやり方は載っていない。
Client Initialization | Socket.IO
- Reactを利用している例。 socket.io で初めてチャット機能を作ってみる
前提
環境は以下の記事の通り、Webサーバ用コンテナと画面サーバ用コンテナを用意し、各サーバを立てている状況。
おそらくこんなイメージ。(間違っていたら修正します)
Webサーバ側の設定
socket.ioのインストール
socket.ioをインストールする。
$ yarn add socket.io
index.jsの変更
Webサーバ側のindex.js
は以下の記載とする。
index.js
// 基本設定 const express = require("express"); const portNumber = 3000; const app = express(); // Expressを利用したサーバ作成 const server = require("http").createServer(app); // Expressを用いないserverも必要なので作成 // 別オリジンからのアクセスを許可する(CORSモジュール利用) const cors = require("cors"); app.use(cors()); // HTTPアクセス時の応答を定義 app.get("/", (req, res) => { res.status(200).send("OK!"); }); // サーバーオブジェクトsocketioを作成する const { Server } = require("socket.io"); const io = new Server(server, { cors: { // corsモジュールでは上手くCORSできないため、Server作成時の引数にオプションを追加する origin: "*", methods: ["GET", "POST"], }, }); // ブラウザから接続されたときの処理を定義する io.on("connection", (socket) => { // ブラウザから接続されたときの処理 console.log("a user connected"); socket.on("disconnect", () => { // ブラウザが切断したときの処理 console.log("user disconnected"); }); }); // serverをPORT3000で待ち受ける。 // ※app.listenだとNG。 server.listen(portNumber); console.log(`Web server is on. PortNumber is ${portNumber}.`);
解説
基本設定
以下の部分は、基本設定になるため過去の記事を参照。Expressサーバのapp
と、createServerで作ったserver
の2つがあることに注意。listen
する際はcreateServerで作ったserver
を利用している。
// 基本設定 const express = require("express"); const portNumber = 3000; const app = express(); // Expressを利用したサーバ作成 const server = require("http").createServer(app); // Expressを用いないserverも必要なので作成 // 別オリジンからのアクセスを許可する(CORSモジュール利用) const cors = require("cors"); app.use(cors()); // HTTPアクセス時の応答を定義 app.get("/", (req, res) => { res.status(200).send("OK!"); }); // serverをPORT3000で待ち受ける。 // ※app.listenだとNG。 server.listen(portNumber); console.log(`Web server is on. PortNumber is ${portNumber}.`);
過去の記事
■WEBサーバと画面サーバを作成して相互に通信させる - エンジニアを目指す日常ブログ
■
Node.js + Express でWEB-APIサーバを作成する - エンジニアを目指す日常ブログ
クライアントとの接続
Socket.ioサーバの作成は以下の記載で実施する。
const { Server } = require("socket.io"); const io = new Server(server)
公式ドキュメント socket.io
CORSについて
CORSについては、cors
モジュールを利用すれば問題ないかと思ったが、これでは接続できなかった。
そのため以下のドキュメントに従って設定を行なった。 socket.io
// const io = new Server(server)を書き換え const io = new Server(server, { cors: { // corsモジュールでは上手くCORSできないため、Server作成時の引数にオプションを追加する origin: "*", methods: ["GET", "POST"], }, });
ブラウザからの接続時の挙動
以下の記載をすることで、ブラウザから接続された際にログを出力することができる。
io.on("connection", (socket) => { console.log("a user connected"); });
また、接続しているときに切断された場合は再度ログを出力するためには、以下の記載に変更する。接続されたときの処理の中に、切断されたときの処理が記載されていることに注意する。
io.on("connection", (socket) => { // ブラウザから接続されたときの処理 console.log("a user connected"); socket.on("disconnect", () => { // ブラウザが切断したときの処理 console.log("user disconnected"); }); });
画面サーバ側の設定
socket.ioとsocket.io-clientをインストール
画面サーバにモジュールをインストールする。
$ yarn add socket.io-client
もしかしたらsocket.io
は不要かも。
$ yarn add socket.io
以下のページを参照。
Client Initialization | Socket.IO
ちなみに、socket.io-client
をインストールしない方法としてindex.html
に以下記載を追加したり色々試してみたが、うまくいかなかった。
<script src="/socket.io/socket.io.js"></script>
App.tsxの変更
App.tsx
に以下記載を追加する。
App.tsx
import React from "react"; import "./App.css"; // socket.io-clientをインポートする import { io } from "socket.io-client"; function App() { // Webサーバとの接続を確立 // ※Webサーバと別ドメインの場合には、io()に引数が必要 const socket = io("http://localhost:3000"); // サーバに接続できた場合のイベント処理を定義する socket.on("connect", () => { console.log(`socket.connectを出力`); console.log(socket.connect()); // サーバに接続できたかどうかを表示 }); return ( <div className="App"> <h1>画面サーバからの返却</h1> </div> ); } export default App;
解説
io()
以下の記載でWebサーバに接続している。
const socket = io("http://localhost:3000");
ドメインの異なるWebサーバに接続する際は引数にURLを入れる必要がある。
socket.on
socket.on("connect", () => { });
socket.on()
は、イベント名と処理を引数に取る関数。イベント名は自分で決めることができる。このイベント名をキーにしてサーバと情報をやり取りする。
一方で、"connect"
は事前に定義された特別なイベントであり、サーバに接続したことを示す。今回のように書くとサーバ接続時に実行したい処理を記載できる。
socket.io
socket.connect()
socket.connect()
を利用すると、サーバへの接続時の情報を取得できる。
socket.io
接続できたかどうかの二値だけであれば、socket.connected()
が使える。
接続結果
Webサーバと画面サーバを起動して、画面サーバlocalhost:8000
にアクセスすると、以下のようにコンソールに接続情報が表示された。
また、画面サーバ側もコンソールログが表示されていることが確認できた。
$ node index.js Web server is on. PortNumber is 3000. a user connected a user connected
※1回ブラウザにアクセスすると2回接続しているように見えるので要調査。
おわりに
画面サーバ(React)とWebサーバ(Node.js)を別々に構築して、クライアントとWebサーバ間をSocket.ioで接続することができた。