将 socket.io 从 v2 升级到 v3

socket.io 及其相关库(例如 socket.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