Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where do I add this websocket code in the new nuxt.js setup since it does not have server?

  • I am using the new version of Nuxt which does not come with a server folder
  • In the old version, you had a server folder and an index.js which contained the app
  • I want to add the websocket WS library with the new version of NuxtJS

The library requires an instance of server which you create by calling http.createServer(app) meaning an instance of the running express app. You would use this server instance now to listen to 3000 in the index.js file. Also create a sessionHandler which you obtain by calling session({}) with the express-session library

    const WebSocket = require('ws')
    function websocket({ server, sessionHandler, logger }) {
      // https://github.com/websockets/ws/blob/master/examples/express-session-parse/index.js, if you pass a server instance here 'upgrade' handler will crash
      const wss = new WebSocket.Server({ noServer: true })
      function noop() {}
      function heartbeat() {
        this.isAlive = true
      }
      wss.on('connection', (ws, request, client) => {
        ws.isAlive = true
        ws.on('pong', heartbeat)
        ws.on('message', (msg) => {
          logger.info(`Received message ${msg} from user ${client}`)
          ws.send(true)
        })
      })
      server.on('upgrade', (request, socket, head) => {
        sessionHandler(request, {}, () => {
          logger.info(`${JSON.stringify(request.session)} WEBSOCKET SESSION PARSED`)
          wss.handleUpgrade(request, socket, head, (ws) => {
            wss.emit('connection', ws, request)
          })
        })
      })
      // TODO use a setTimeout here  instead of a setInterval
      setInterval(function ping() {
        // wss.clients => Set
        wss.clients.forEach(function each(ws) {
          if (ws.isAlive === false) return ws.terminate()
          ws.isAlive = false
          ws.ping(noop)
        })
      }, 30000)
      return wss
    }
    module.exports = websocket
  • Does anyone know how I can make this work on the new Nuxt setup without the server folder
like image 504
PirateApp Avatar asked Dec 13 '22 08:12

PirateApp


1 Answers

You can create a custom module and use nuxt hooks to get a server instance on listen event.

Create modules/ws.js:

const WebSocket = require('ws')
const wss = new WebSocket.Server({ noServer: true })

wss.on('connection', ws => {
  ws.on('message', message => {
    console.log('received: %s', message);
  })
  ws.send('Hello')
})

export default function () {
  this.nuxt.hook('listen', server => {
    server.on('upgrade', (request, socket, head) => {
      wss.handleUpgrade(request, socket, head, ws => {
        wss.emit('connection', ws);
      })
    })
  })
}

And register the module in nuxt.config.js:

export default {
  modules: [
    '~/modules/ws'
  ]
}

In your case you could create a module directory instead of a single file to store multiple related files.

Create modules/ws/index.js

const websocket = require('./websocket') // this is your file

export default function () {
  this.nuxt.hook('listen', server => {
    websocket({
      server,
      sessionHandler (request, _, cb) { // example
        cb()
      },
      logger: console // example
    })
  })
}

Then copy your file to modules/ws/websocket.js. You can use module.exports which is CommonJS format or change it into ES Module format, Nuxt(Webpack) can handle that.

In your code I notice that ws.send(true) cause an error TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object. Received type boolean (true) which basically mean you cannot send boolean.

like image 117
User 28 Avatar answered Jan 14 '23 15:01

User 28