socket.io を v2 から v3 にアップグレードする
socket.io と socket.io-redis-adapter や socket.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.
-
For breaking API change
Following the official guide should be fine, and items such as Namespace.connected is renamed to Namespace.sockets and is now a Map and Socket.join() and Socket.leave() are now synchronous need special attention as breaking changes. -
For client change
Replace the event names with new ones such as:
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 insocket-io-redis
adapter since v6.x regarding how redispubClient
andsubClient
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
andsubClient
) would be created for each single namespace. This change would cause a huge issue for use cases where lots ofnamespaces
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.
参考文献