如何在Adonis 4.1.0中使用Socket.io?求兼容解决方案
在Adonis 4.1.0中集成Socket.io的可行方案
刚好我之前在Adonis 4.x版本上折腾过Socket.io的集成,给你整理几个亲测靠谱的方案,适配你的场景:
方案一:直接在Adonis HTTP服务器上挂载Socket.io
这是最轻量化的方案,不用额外启动独立服务,直接复用Adonis的现有HTTP服务器:
- 安装依赖:
npm install socket.io
- 修改
start/server.js,获取原生HTTP服务器实例并挂载Socket.io:
const socketIo = require('socket.io') const { Ignitor } = require('@adonisjs/ignitor') new Ignitor(require('@adonisjs/fold')) .appRoot(__dirname) .fireHttpServer() .then((httpServer) => { // 初始化Socket.io,可配置跨域规则 const io = socketIo(httpServer, { cors: { origin: "http://your-frontend-domain", // 替换成你的前端域名 methods: ["GET", "POST"] } }) // 处理连接事件 io.on('connection', (socket) => { console.log('用户已连接:', socket.id) // 监听客户端发送的消息 socket.on('send-message', (data) => { console.log('收到消息:', data) // 广播给所有在线客户端 io.emit('receive-message', data) }) socket.on('disconnect', () => { console.log('用户已断开:', socket.id) }) }) })
优点:零额外服务开销,配置简单,适合中小型单实例应用。
方案二:独立Socket.io服务+Redis适配器(分布式场景)
如果你的应用是多实例部署,直接挂载的方案无法跨实例广播消息,这时候可以用Redis做状态共享:
- 安装依赖:
npm install socket.io socket.io-redis redis
- 创建独立的Socket服务文件
start/socketServer.js:
const http = require('http') const socketIo = require('socket.io') const redisAdapter = require('socket.io-redis') const server = http.createServer() const io = socketIo(server, { cors: { origin: "http://your-adonis-domain", methods: ["GET", "POST"] } }) // 配置Redis适配器,实现跨实例消息同步 io.adapter(redisAdapter({ host: 'localhost', port: 6379 })) io.on('connection', (socket) => { socket.emit('welcome', '已连接到Socket.io服务') // 这里编写你的业务逻辑,比如房间管理、消息推送等 }) // 启动Socket服务,监听独立端口 server.listen(3001, () => { console.log('Socket.io服务运行在端口3001') })
- 在
package.json中添加启动脚本:
"scripts": { "start": "node server.js", "start:socket": "node start/socketServer.js" }
启动时同时运行Adonis和Socket服务即可。客户端连接时需指定Socket服务端口:const socket = io('http://localhost:3001')。
方案三:使用社区适配的Adonis Socket.io包
社区有维护适配Adonis 4.x的Socket.io集成包,写法更贴合Adonis生态:
- 安装适配包:
npm install adonis-socket.io
- 在
start/app.js的providers数组中注册Provider:
providers: [ // ...其他provider 'adonis-socket.io/providers/SocketIoProvider' ]
- 创建Socket控制器,比如
app/Controllers/Ws/ChatController.js:
class ChatController { async onConnection(socket) { // 可选:在这里做鉴权,比如通过token获取用户信息 const token = socket.handshake.query.token try { const user = await use('Auth').verify(token) socket.user = user console.log('用户鉴权通过:', user.username) } catch (err) { socket.disconnect(true) // 鉴权失败直接断开连接 } // 监听客户端事件 socket.on('send-message', (data) => { // 广播给当前房间的其他用户 socket.broadcast.emit('new-message', { ...data, user: socket.user.username }) }) } } module.exports = ChatController
- 在
start/routes.js中配置Socket路由:
const Ws = use('Ws') Ws.route('/chat', 'ChatController.onConnection', { auth: false // 根据需求设置是否强制鉴权 })
优点:完全遵循Adonis的开发范式,适合熟悉Adonis生态的开发者。
额外注意事项
- 跨域配置:务必根据你的前端域名配置Socket.io的
cors选项,避免跨域错误; - 版本兼容:Adonis 4.1.0适配的Node.js版本建议在8.x-12.x,Socket.io选择2.x或3.x版本更稳妥,避免最新版本的兼容性问题;
- 鉴权逻辑:无论哪种方案,都可以在
connection事件中通过客户端传递的token,调用Adonis的Auth服务完成用户鉴权,非法连接直接断开。
内容的提问来源于stack exchange,提问作者Tijan Manandhar
相关产品推荐
相关产品推荐

