WebSocket is not defined : node_modules/lib0/websocket.js:25:23

I’m having this issue:

(base) raphy@pc:~/y-webrtc-playing$ node ./bin/server.js 
  Signaling server running on localhost: 5555

(base) raphy@pc:~/y-webrtc-playing$ node client.js 
file:///home/raphy/y-webrtc-playing/node_modules/lib0/websocket.js:25
    const websocket = new WebSocket(wsclient.url)
                      ^

ReferenceError: WebSocket is not defined
    at setupWS (file:///home/raphy/y-webrtc-playing/node_modules/lib0/websocket.js:25:23)
    at new WebsocketClient (file:///home/raphy/y-webrtc-playing/node_modules/lib0/websocket.js:122:5)
    at new SignalingConn (file:///home/raphy/y-webrtc-playing/node_modules/y-webrtc/src/y-webrtc.js:461:5)
    at file:///home/raphy/y-webrtc-playing/node_modules/y-webrtc/src/y-webrtc.js:596:75
    at Module.setIfUndefined (file:///home/raphy/y-webrtc-playing/node_modules/lib0/map.js:49:24)
    at file:///home/raphy/y-webrtc-playing/node_modules/y-webrtc/src/y-webrtc.js:596:33
    at Array.forEach (<anonymous>)
    at WebrtcProvider.connect (file:///home/raphy/y-webrtc-playing/node_modules/y-webrtc/src/y-webrtc.js:595:24)
    at new WebrtcProvider (file:///home/raphy/y-webrtc-playing/node_modules/y-webrtc/src/y-webrtc.js:581:10)
    at file:///home/raphy/y-webrtc-playing/client.js:7:18

This the client.js :

/* eslint-env browser */

import * as Y from 'yjs'
import { WebrtcProvider } from 'y-webrtc'

const ydoc = new Y.Doc()
const provider = new WebrtcProvider('webrtc-test', ydoc, { signaling: ['ws://localhost:4444'] })
const yarray = ydoc.getArray()

provider.on('synced', synced => {
  // NOTE: This is only called when a different browser connects to this client
  // Windows of the same browser communicate directly with each other
  // Although this behavior might be subject to change.
  // It is better not to expect a synced event when using y-webrtc
  console.log('synced!', synced)
})

yarray.observeDeep(() => {
  console.log('yarray updated: ', yarray.toJSON())
})

// @ts-ignore
window.example = { provider, ydoc, yarray }

This is the server.js :

#!/usr/bin/env node

import ws from 'ws'
import http from 'http'
import * as map from 'lib0/map'

const wsReadyStateConnecting = 0
const wsReadyStateOpen = 1
const wsReadyStateClosing = 2 // eslint-disable-line
const wsReadyStateClosed = 3 // eslint-disable-line

const pingTimeout = 30000

const port = process.env.PORT || 5555
// @ts-ignore
const wss = new ws.Server({ noServer: true })

const server = http.createServer((request, response) => {
  response.writeHead(200, { 'Content-Type': 'text/plain' })
  response.end('okay')
})

/**
 * Map froms topic-name to set of subscribed clients.
 * @type {Map<string, Set<any>>}
 */
const topics = new Map()

/**
 * @param {any} conn
 * @param {object} message
 */
const send = (conn, message) => {
  if (conn.readyState !== wsReadyStateConnecting && conn.readyState !== wsReadyStateOpen) {
    conn.close()
  }
  try {
    conn.send(JSON.stringify(message))
  } catch (e) {
    conn.close()
  }
}

/**
 * Setup a new client
 * @param {any} conn
 */
const onconnection = conn => {
  /**
   * @type {Set<string>}
   */
  const subscribedTopics = new Set()
  let closed = false
  // Check if connection is still alive
  let pongReceived = true
  const pingInterval = setInterval(() => {
    if (!pongReceived) {
      conn.close()
      clearInterval(pingInterval)
    } else {
      pongReceived = false
      try {
        conn.ping()
      } catch (e) {
        conn.close()
      }
    }
  }, pingTimeout)
  conn.on('pong', () => {
    pongReceived = true
  })
  conn.on('close', () => {
    subscribedTopics.forEach(topicName => {
      const subs = topics.get(topicName) || new Set()
      subs.delete(conn)
      if (subs.size === 0) {
        topics.delete(topicName)
      }
    })
    subscribedTopics.clear()
    closed = true
  })
  conn.on('message', /** @param {object} message */ message => {
    if (typeof message === 'string') {
      message = JSON.parse(message)
    }
    if (message && message.type && !closed) {
      switch (message.type) {
        case 'subscribe':
          /** @type {Array<string>} */ (message.topics || []).forEach(topicName => {
            if (typeof topicName === 'string') {
              // add conn to topic
              const topic = map.setIfUndefined(topics, topicName, () => new Set())
              topic.add(conn)
              // add topic to conn
              subscribedTopics.add(topicName)
            }
          })
          break
        case 'unsubscribe':
          /** @type {Array<string>} */ (message.topics || []).forEach(topicName => {
            const subs = topics.get(topicName)
            if (subs) {
              subs.delete(conn)
            }
          })
          break
        case 'publish':
          if (message.topic) {
            const receivers = topics.get(message.topic)
            if (receivers) {
              receivers.forEach(receiver =>
                send(receiver, message)
              )
            }
          }
          break
        case 'ping':
          send(conn, { type: 'pong' })
      }
    }
  })
}
wss.on('connection', onconnection)

server.on('upgrade', (request, socket, head) => {
  // You may check auth of request here..
  /**
   * @param {any} ws
   */
  const handleAuth = ws => {
    wss.emit('connection', ws, request)
  }
  wss.handleUpgrade(request, socket, head, handleAuth)
})

server.listen(port)

console.log('Signaling server running on localhost:', port)

I’ve put everything into this repo: https://github.com/raphael10-collab/y-webrtc-playing.git

How to solve the problem?

1 Like

You are running the client in Node.js, not in browser. There is no WebSocket in Node.js. Import client.js inside .html file and see what happens then.

3 Likes

Hi!!!
Thank you for helping.

With:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>y-webrtc demo</title>
</head>
<body>
  <button type="button" id="y-connect-btn">Disconnect</button>
  <script type="text/javascript" src="./client.js"></script>
</body>

It seems fine actually now. Thank you!

I opened an another question here: `y-webrtc` : WebSocket connection failed : 'wss://y-webrtcsignaling-eu.herokuapp.com'

what if i want to get updates on nodejs only not in browser ?

The browser has a native WebSocket and WebRTC object that can be used to create connections. These do not exist in nodejs. You can try to polyfill WebSocket and WebRTC functionality. For websocket, there is the ws package.