Using socket.io

Author - Virk

Published on Mon Jun 08 2020

Socket.io is a very popular library for real-time and bidirectional communication. In this guide, we will learn how to use socket.io with AdonisJS.

The first step is to install the package from the npm package registry.

npm i socket.io
yarn add socket.io

Next, let's create a service class responsible for starting the socketio server and provide us a reference to it.

The code for the service can be anywhere inside your codebase. I prefer keeping it inside the ./app/Services directory.

app/Services/Ws.ts
import { Server } from 'socket.io'
import AdonisServer from '@ioc:Adonis/Core/Server'
class Ws {
public io: Server
private booted = false
public boot() {
/**
* Ignore multiple calls to the boot method
*/
if (this.booted) {
return
}
this.booted = true
this.io = new Server(AdonisServer.instance!)
}
}
export default new Ws()

Next, let's create a start/socket.ts file and paste the following contents inside it. Like the routes file, we will use this file to listen to the incoming socket connections.

start/socket.ts
import Ws from 'App/Services/Ws'
Ws.boot()
/**
* Listen for incoming socket connections
*/
Ws.io.on('connection', (socket) => {
socket.emit('news', { hello: 'world' })
socket.on('my other event', (data) => {
console.log(data)
})
})

Finally, import the above-created file inside the providers/AppProvider.ts file under the ready method.

The ready method runs after the AdonisJS HTTP server is ready, and this is when we should establish the socketio connection.

providers/AppProvider.ts
import { ApplicationContract } from '@ioc:Adonis/Core/Application'
export default class AppProvider {
constructor(protected app: ApplicationContract) {}
public async ready() {
if (this.app.environment === 'web') {
await import('../start/socket')
}
}
}

That's all you need to do to set up socket.io. Let's take a step further and also test that we can establish a connection from the browser.

Client setup

We will use the CDN build of socketio-client to keep things simple. Let's open the resources/views/welcome.edge and add the following scripts to the page.

resources/views/welcome.edge
<body>
<!-- Rest of markup -->
<script src="https://cdn.socket.io/4.0.1/socket.io.min.js"></script>
<script>
const socket = io()
socket.on('news', (data) => {
console.log(data)
socket.emit('my other event', { my: 'data' })
})
</script>
</body>
</html>

Let's start the development server by running node ace serve --watch and open http://localhost:3333 in the browser to test the integration.

Broadcast from anywhere

Since we have abstracted the socketio setup to a service class, you can import it from anywhere inside your codebase to broadcast events. For example:

import Ws from 'App/Services/Ws'
class UsersController {
public async store() {
Ws.io.emit('new:user', { username: 'virk' })
}
}

Configure CORS

The socketio connection uses the underlying Node.js HTTP server directly, and hence the AdonisJS CORS setup will not work with it.

However, you can configure cors with socketio directly as follows.

class Ws {
public io: Server
private booted = false
public boot() {
/**
* Ignore multiple calls to the boot method
*/
if (this.booted) {
return
}
this.booted = true
this.io = new Server(AdonisServer.instance!, {
cors: {
origin: '*'
}
})
}
}