Nuxtでの使い方
このガイドでは、Nuxtアプリケーション内でSocket.IOを使用する方法を説明します。
サーバー
内部的には、NuxtはHTTPリクエストを処理するためにNitroを使用しています。
Socket.IOサーバーをNitroサーバーにアタッチするには、2つのステップがあります。
WebSocketsを有効にする
NitroでのWebSocketsのサポートは現在実験的であるため、手動で有効にする必要があります。
nuxt.config.js
// https://nuxt.dokyumento.jp/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
  devtools: {
    enabled: true
  },
+ nitro: {
+   experimental: {
+     websocket: true
+   },
+ }
})
参考: https://nitro.unjs.io/guide/websocket
Socket.IOサーバーをフックする
Socket.IOサーバーは、Nitroプラグインで作成されます。
server/plugins/socket.io.ts
import type { NitroApp } from "nitropack";
import { Server as Engine } from "engine.io";
import { Server } from "socket.io";
import { defineEventHandler } from "h3";
export default defineNitroPlugin((nitroApp: NitroApp) => {
  const engine = new Engine();
  const io = new Server();
  io.bind(engine);
  io.on("connection", (socket) => {
    // ...
  });
  nitroApp.router.use("/socket.io/", defineEventHandler({
    handler(event) {
      engine.handleRequest(event.node.req, event.node.res);
      event._handled = true;
    },
    websocket: {
      open(peer) {
        const nodeContext = peer.ctx.node;
        const req = nodeContext.req;
        // @ts-expect-error private method
        engine.prepare(req);
        const rawSocket = nodeContext.req.socket;
        const websocket = nodeContext.ws;
        // @ts-expect-error private method
        engine.onWebSocket(req, rawSocket, websocket);
      }
    }
  }));
});
はい、完了です!
クライアント
クライアント側では、Vue 3ガイドからのすべてのヒントが有効です。
唯一の違いは、Socket.IOクライアントをサーバーサイドレンダリング(SSR)から除外する必要があることです。
構成
├── components
│ ├── Connection.client.vue
│ └── socket.ts
...
components/socket.ts
import { io } from "socket.io-client";
export const socket = io();
components/Connection.client.vue
<script setup>
import { socket } from "./socket";
const isConnected = ref(false);
const transport = ref("N/A");
if (socket.connected) {
  onConnect();
}
function onConnect() {
  isConnected.value = true;
  transport.value = socket.io.engine.transport.name;
  socket.io.engine.on("upgrade", (rawTransport) => {
    transport.value = rawTransport.name;
  });
}
function onDisconnect() {
  isConnected.value = false;
  transport.value = "N/A";
}
socket.on("connect", onConnect);
socket.on("disconnect", onDisconnect);
onBeforeUnmount(() => {
  socket.off("connect", onConnect);
  socket.off("disconnect", onDisconnect);
});
</script>
<template>
<div>
  <p>Status: {{ isConnected ? "connected" : "disconnected" }}</p>
  <p>Transport: {{ transport }}</p>
</div>
</template>
注記
Connection.client.vue の .client サフィックスは、コンポーネントがクライアント側でのみレンダリングされる(SSRなし)ことを示します。
参考: https://nuxt.dokyumento.jp/docs/guide/directory-structure/components#client-components
上記の例では、transport変数はSocket.IO接続を確立するために使用される低レベルトランスポートであり、次のいずれかになります。
- HTTPロングポーリング ("polling")
- WebSocket ("websocket")
- WebTransport ("webtransport")
すべてがうまくいけば、次のように表示されます。
Status: connected
Transport: websocket
その後、Socket.IOサーバーとクライアント間でメッセージを交換できます。
- socket.emit()を使用してメッセージを送信
socket.emit("hello", "world");
- socket.on()を使用してメッセージを受信
socket.on("hello", (value) => {
  // ...
});
以上です、お読みいただきありがとうございます!