Upgrade socket.io from v2 to v3

socket.io and its related libraries such as socket.io-redis-adapter and socket.io-redis-emitter had a few breaking changes in either functions or behaviors since v3 which might cause issues during the v2-to-v3 migration. This post lists what was encountered and how to solve it for specific use cases based on hands-on experience.

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.

References

js javascript socket.io nodejs