This content originally appeared on DEV Community and was authored by Arthur Emanuel
In this tutorial we'll build a broadcasting module for AdonisJS which resembles Laravel Broadcasting features (you can even use Laravel Echo). This module will cover up many of the websockets use cases in a simple manner.
It is great for cases where the clients need to receive data in real-time, but don't need to send data in real-time.
Good use cases are:
- Chats
- Live dashboards
- Sport scores
Bad use cases are:
- Games
- Work together platforms
Let's build it!
Scaffolding a new app
Create a new AdonisJS project
$ npm init create-adonis-ts-app broadcasting
$ yarn create adonis-ts-app broadcasting
When prompted which project structure, select web and flag
Configure webpack for compiling frontend assets? true
Setting up our Broadcast service
Our broadcast module will be based in an open-source Pusher compatible server called pWS.
First, we will install it
$ npm i @soketi/pws
$ yarn add @soketi/pws
We can start the server by running
$ npm pws-server start
$ yarn pws-server start
But we need to configure it before running, so we will make a configuration file for it in config/broadcasting.ts
// config/broadcasting.ts
import Env from '@ioc:Adonis/Core/Env'
const broadcastingConfig = {
port: Env.get('BROADCASTING_PORT', 6001),
appId: Env.get('BROADCASTING_APP_ID', 'app-id'),
appKey: Env.get('BROADCASTING_APP_KEY', 'app-key'),
appSecret: Env.get('BROADCASTING_APP_KEY', 'app-secret'),
}
export default broadcastingConfig
The configs won't get magically loaded into pWS, so we will make a command to start it. To start it we will use execa. So install it using:
$ npm i execa
$ yarn add execa
and create a command with
$ node ace make:command StartPws
The command will look like this:
// commands/StartPws.ts
import { BaseCommand } from '@adonisjs/core/build/standalone'
import execa from 'execa'
export default class StartPws extends BaseCommand {
public static commandName = 'start:pws'
public static description = 'Start the pWS server with Adonis Configs'
public static settings = {
loadApp: true,
stayAlive: true,
}
public async run() {
const broadcastingConfig = this.application.config.get('broadcasting')
const command = `
PORT=${broadcastingConfig.port}
DEFAULT_APP_ID=${broadcastingConfig.appId}
DEFAULT_APP_KEY=${broadcastingConfig.appKey}
DEFAULT_APP_SECRET=${broadcastingConfig.appSecret}
yarn pws-server start`
await execa(command, { shell: true }).stdout?.pipe(process.stdout)
}
}
After creating the command, we need to regenerate the ace manifest, so it catches our new command, do it by running:
$ node ace generate:manifest
As pWS is a drop-in Pusher replacement, we can interact with it using any Pusher client, and we will do it. Start by installing the node Pusher client:
$ npm i pusher
$ yarn add pusher
Then we will create a service to interact with the pWS server, it can be done as a simple service or as a AdonisJS provider, in this tutorial we will go the service way.
// app/Services/Broadcast.ts
import Pusher from 'pusher'
import broadcastingConfig from 'Config/broadcasting'
import Env from '@ioc:Adonis/Core/Env'
class Broadcast {
private pusher = new Pusher({
host: Env.get('HOST', 'localhost'),
port: broadcastingConfig.port,
appId: broadcastingConfig.appId,
key: broadcastingConfig.appKey,
secret: broadcastingConfig.appSecret,
})
public async broadcast(channel: string | string[], event: string, data: any) {
const response = await this.pusher.trigger(channel, event, data)
return response
}
}
export default new Broadcast()
To listen to events in our frontend we can use PusherJS paired with Laravel Echo. Start by installing both:
$ npm i -D laravel-echo pusher-js
$ yarn add -D laravel-echo pusher-js
And setting up them in our frontend:
<!-- resources/views/welcome.edge -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>AdonisJS - A fully featured web framework for Node.js</title>
@entryPointStyles('app')
@entryPointScripts('app')
</head>
<body>
<main>
<div>
<h1 class="title">It Works!</h1>
<p class="subtitle">Congratulations, you have just created your first AdonisJS app.</p>
<form method="POST" action="/message">
<input name="message" type="text" />
<button>Send Message</button>
</form>
</div>
</main>
</body>
</html>
// resources/js/app.js
import '../css/app.css'
import Echo from 'laravel-echo'
window.Pusher = require('pusher-js')
window.Echo = new Echo({
broadcaster: 'pusher',
wsHost: 'localhost',
wsPort: 6001,
forceTLS: false,
disableStats: true,
key: 'app-key',
namespace: '',
})
window.Echo.channel('messages').listen('message', (e) => {
alert(JSON.stringify(e))
})
After setting up that, we just need to setup our message route to broadcast a message event:
// start/routes.ts
import Route from '@ioc:Adonis/Core/Route'
import Broadcast from 'App/Services/Broadcast'
Route.get('/', async ({ view }) => {
return view.render('welcome')
})
Route.post('/message', async ({ request, response }) => {
const message = request.input('message')
await Broadcast.broadcast('messages', 'message', { message })
return response.redirect().back()
})
It's alive!
But it still doesn't works for private or presence channels, we will address that in next tutorial, stay tuned!
This content originally appeared on DEV Community and was authored by Arthur Emanuel
Arthur Emanuel | Sciencx (2021-10-05T01:12:16+00:00) Broadcasting in AdonisJS. Retrieved from https://www.scien.cx/2021/10/05/broadcasting-in-adonisjs/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.