socket.io を v2 から v3 にアップグレードする

socket.iosocket.io-redis-adaptersocket.io-redis-emitter などの関連ライブラリは、v3 以降、機能または動作にいくつかの重大な変更があり、v2 から v3 への移行中に問題が発生する可能性があります。この投稿では、実際の経験に基づいて、特定のユースケースで発生した問題とその解決方法をリストします。

Upgrade guide

Basically read the Migrating from 2.x to 3.0 official guide, then:

  • For npm packages
-   "socket.io": "2.3.0",
-   "socket.io-emitter": "3.1.1",
-   "socket.io-redis": "5.4.0" ,
+   "socket.io": "3.1.2",
+   "socket.io-emitter": "3.2.0",
+   "socket.io-redis": "6.0.1",
  • For server config
const sio = require('socket.io');

//...

this.io = sio(this.http_server, {
  // enable compatibility for v2 clients (must; during migration)
  allowEIO3: true,
  // the same as the default value in v2 (optional; use case specific)
  maxHttpBufferSize: 10e7,
  // the same as the default value in v2 (optional; use case specific)
  perMessageDeflate: true,
  cors: {
    // must; if to enable cors for any clients; cannot use '*' due to the credentials option below
    origin: true,
    // must; because v2 socket.io clients will set withCredentials: true
    credentials: true,
    // optional; use case specific
    allowHeaders: 'Accept,Authorization,Content-Type,Origin,X-Requested-With',
  },
});

and for cookie option change, the official guide can be referenced here.

socket.on("error", err => {
  console.log(err);
});
// change to
socket.on("connect_error", err => {
  console.log(err.message);
});

and update to add listeners to Manager instead of socket object:

socket.on("reconnect_attempt", () => {});
// change to
socket.io.on("reconnect_attempt", () => {});
  • For redis-adapter behavior change

    Note:
    There was a big behavior change in socket-io-redis adapter since v6.x regarding how redis pubClient and subClient are created. In previous versions, the redis clients are created by the adapter and shared by all namespaces during initialization. However, in the newer versions a new pair of redis clients (pubClient and subClient) would be created for each single namespace. This change would cause a huge issue for use cases where lots of namespaces are used in socket-io server.

    For more details see this issue reported by me during the upgrading.

  • For other tips
    The newer versions were rewritten using TypeScript as well as with newer JavaScript syntaxes from ES6+, there might be issues related to webpack and its plugins not being able to handle the build any more and there might be performance issues related to per message deflation, and so on.

参考文献

javascript socket.io nodejs