DEV Community

Cover image for 8 Best WebSocket Libraries For Node
Ably Blog for Ably

Posted on • Originally published at ably.com

8 Best WebSocket Libraries For Node

As a developer, choosing the right Websocket Node library to integrate into your realtime application project can be a humbling experience. You are faced with a lot of choices that offer different capabilities and features that will allow you to build scalable and efficient applications. However, given the constantly changing landscape, a crucial question remains: have you selected the most suitable one? Are there other options that could enhance your project even more?

In this article, we'll explore the top eight WebSocket libraries and shed light on their advantages and potential limitations to help you discover the tools to take your Node realtime applications to new heights.

But first, let’s take a step back and understand the basics of WebSockets.

What are WebSockets?

WebSockets are a type of communication protocol that enables bidirectional, full-duplex communication channels over a long-lived and single connection between a server and client, usually a web browser. The session connection remains open, saving bandwidth and server resources by avoiding constant re-establishment of connections.

Unlike the conventional model of HTTP's request-response where a client sends a http request and the server responds with a single response, WebSockets allow the server and client to send messages independently and in realtime.

WebSockets are a powerful tool for building interactive web applications that require the server to send updates to the client without the client reloading the page. They are handy for realtime updates, such as chat applications, online gaming, live notifications, collaborative tools, financial trading platforms, and similar applications.

To implement WebSockets, you need JavaScript on the client-side and a server-side technology that supports the WebSocket protocol. One popular choice for this is Node, which has many WebSocket libraries available.

Check out our article on the pros and cons of WebSockets.

Top eight WebSocket libraries for Node

To help you choose the right one for your project, we've compiled a list of the top eight Node WebSocket libraries.

  1. Socket.IO
  2. WS
  3. SockJs
  4. Feathers
  5. µWebSockets
  6. Faye-WebSocket
  7. Primus
  8. SocketCluster

1. Socket.IO

Socket.IO, founded in 2010, is a popular WebSocket library with nearly 59k stars on GitHub and about 3 million weekly npm downloads. It’s used by many top companies, including FlutterWave, and Trello. Socket.IO is optimized to function well in network environments that have intermediary components such as proxies and load balancers. Socket.IO is a go-to WebSocket Node library for many developers.

It also provides a higher-level API that makes it easier for developers to build realtime web application features than raw WebSockets. Socket.IO provides unique features such as rooms and namespaces to build more complex and sophisticated apps. Rooms enable you to group clients and send broadcast messages targeted to specific groups. Conversely, Namespaces create separate communication spaces within your application, which is useful for organizing events and logic.

Pros of Socket.IO

  • Socket.IO uses namespaces to reduce WebSocket connections and save server socket ports.
  • Socket.IO's rooms feature allows flexible many-to-one messaging or broadcasting of events to all connected clients from the server side.
  • In scenarios where WebSocket support is unavailable, Socket.IO offers HTTP long-polling as a reliable alternative for communication.
  • Socket.IO offers a configurable ping/pong heartbeat mechanism to detect connection status and automatically reconnect clients upon disconnection.

Cons of Socket.IO

  • Socket.IO provides an at-most-once messaging guarantee by default and cannot guarantee exactly-once messaging semantics. It is possible to configure Socket.IO to provide at-least-once guarantees, but keep it in mind that this increases engineering complexity.
  • Socket.IO has limited native security features. It does not provide end-to-end encryption or token generation and renewal mechanisms for authentication.
  • Socket.IO cannot be used with any other WebSocket implementation. This means that a plain WebSocket client cannot be used with a Socket.IO server, and a Socket.IO client cannot connect to a plain WebSocket server.
  • Socket.IO is designed to work within a single region and may not be suitable for a multi-region architecture. This can result in increased latency and potential system downtime in the event of an outage at the data center where your Socket.IO servers are hosted.

Getting started with Socket.IO

Socket.IO enables realtime, bidirectional, and event-based communication. It works on every platform, browser, or device, focusing equally on reliability and speed. To start using Socket.IO, you need to install the library into your working directory with npm.

To install Socket.IO, run the following command on your terminal:

 npm install socket.io
 npm install express
Enter fullscreen mode Exit fullscreen mode

Here is a simple server.js on how to use Socket.IO.

// Import the Express framework
const express = require('express');

// Create an Express application
const app = express();

// Create an HTTP server using Express
const httpServer = require('http').createServer(app);

// Create a WebSocket server using Socket.IO and attach it to the HTTP server
const io = require('socket.io')(httpServer);

// Handle WebSocket connections
io.on('connection', (socket) => {
  console.log('A user connected'); // Log when a user connects

  // Handle disconnection
  socket.on('disconnect', () => {
    console.log('User disconnected'); // Log when a user disconnects
  });
Enter fullscreen mode Exit fullscreen mode

Before deciding to use Socket.IO for your web application project, it's important to carefully consider the pros and cons of using it and explore alternative options.

2. WS

The WS library is a well-known Node.js tool for WebSocket communication. It is lightweight, easy to use, and efficient, with functionalities that enable client management, message exchange, and WebSocket connection handling. It offers only the necessary WebSockets features without any extra overhead.

WS has a user base of 17.7 million people and over 20,000 forks. It also has clear and concise documentation, with examples and API references, to help developers understand how to integrate it into their projects.

Pros of WS

  • WS offers a lightweight, simple, and efficient implementation of the WebSocket protocol.
  • WS is a good choice for applications where raw WebSocket communication is preferred, especially when there is a need for complete control over the WebSocket protocol, and you want to optimize performance, minimize overhead, or design custom features.

Cons of WS

  • Requires a good understanding of WebSocket protocol details.
  • WS requires extra code to handle functions such as reconnection, fallbacks, and more complex abstractions.
  • Compared to other libraries like Socket.IO, WS has limited abstraction, which can lead to increased development time and complexity.

Getting started With WS

The WS library is useful for creating WebSocket servers and clients in Node. It offers a simple and easy-to-use API, allowing WebSocket servers to wait for incoming connections and clients to initiate connections with servers. Once a connection is established, both parties can communicate in realtime by exchanging messages. With the WS library handling the technical aspects of the WebSocket protocol, developers can concentrate on their application-specific tasks.

To install the WS library, run:

npm install ws
Enter fullscreen mode Exit fullscreen mode

A basic WebSocket server using the WS library:

// Import the WebSocket library
const WebSocket = require('ws');

// Create a WebSocket server on port 8080
const WebSocketServer = new WebSocket.Server({ port: 8080 });

// Event handler for when a client connects
WebSocketServer.on('connection', (clientSocket) => {
  console.log('A client connected'); // Log when a client connects

  // Event handler for when the server receives a message from a client
  clientSocket.on('message', (message) => {
    console.log(`Received: ${message}`); // Log the received message
    clientSocket.send(`You said: ${message}`); // Send a response to the client
  });

  // Event handler for when a client disconnects
  clientSocket.on('close', () => {
    console.log('Client disconnected'); // Log when a client disconnects
  });
});
Enter fullscreen mode Exit fullscreen mode

3. SockJS

SockJS is a Node library that offers a WebSocket-like object with a JavaScript API that can work across different browsers. SockJS was designed because not all browsers support the WebSocket protocol, especially not legacy versions. It provides you with a JavaScript API that creates fast, two-way communication and cross-domain communication channels between the web server and the browser. It adheres to the HTML5 WebSocket API but can switch to browser-specific protocols if necessary.

Pros of SockJS

  • It automatically falls back to alternative full-duplex communication when the user's browser does not support WebSockets.
  • SockJS offers an API with syntax identical to the WebSockets API, allowing you to switch to and from a WebSocket setup. If you run into browser compatibility issues, you can easily switch to SockJS without having to rewrite your WebSocket code.

Cons of SockJS

Getting started with SockJS

Like every other Node WebSocket library, to initiate a SockJS socket connection, the client sends a handshake request to the server, which responds with a handshake confirmation. Once the handshake is complete, the connection switches to a bidirectional binary protocol. With the connection established, both parties can exchange messages.

To install SockJs:

 npm install sockjs

Enter fullscreen mode Exit fullscreen mode

A basic WebSocket server using the SockJS library:

// Import the required modules
const http = require('http');
const sockjs = require('sockjs');

// Create a SockJS server instance with a prefix
const echoServer = sockjs.createServer({ prefix: '/echo' });

// Handle incoming connections to the SockJS server
echoServer.on('connection', function(connection) {
  // Handle incoming data from clients
  connection.on('data', function(message) {
    // Send the received message back to the client
    connection.write(message);
  });

  // Handle the connection close event
  connection.on('close', function() {
    // Perform any necessary cleanup or handling here (optional)
  });
});

// Create an HTTP server
const httpServer = http.createServer();

// Attach the SockJS server to the HTTP server
echoServer.installHandlers(httpServer);

// Listen on a specific IP address and port
httpServer.listen(9999, '0.0.0.0', () => {
  console.log('SockJS server is running on port 9999');
});
Enter fullscreen mode Exit fullscreen mode

4. µWebSockets

µWebSockets, pronounced as "microWebSocket”, is a WebSocket library written in C++ and has Node.js bindings. Its design focuses on being efficient and scalable, making it ideal for applications that require high concurrency and low latency.

It is an implementation of HTTP and WebSockets that is both simple and highly optimized. It includes built-in Pub/Sub support, HTTP routing, TLS 1.3, IPv6, and permessage-deflate. It has been extensively tested and is widely used by many end users daily.

Pros of µWebSockets

  • µWebSockets .js is demonstrated to perform at levels 8.5x that of Fastify and at least 10x that of Socket.IO.
  • µWebSockets is designed to be lightweight and efficient, making it suitable for resource-constrained environments.
  • It provides high-performance and low latency WebSocket communication, making it ideal for realtime applications.
  • The library has minimal dependencies, simplifying installation and reducing potential conflicts with other libraries.

Cons of µWebSockets

  • While not difficult, learning to use µWebSockets effectively may take time, especially for developers unfamiliar with C++ or WebSocket protocol intricacies.
  • New developers may have difficulty finding guidance on how to use µWebSockets due to the lack of extensive documentation and tutorials.

Getting started with µWebSockets

Install µWebSockets using npm for Node.js v18.17.0

npm install “uNetworking/uWebSockets.js#v20.31.0”

Enter fullscreen mode Exit fullscreen mode

However, if you encounter any issue with a version of µWS that is not compatible with your Node.js build, you’ll have to compile the binaries on your target machine:

# Clone the repo w/ submodules
git clone --recursive https://github.com/uNetworking/uWebSockets.js.git
# Cd into the folder
cd uWebSockets.js
# build
make
Enter fullscreen mode Exit fullscreen mode

Here is an example of the basic implementation of a WebSocket server using µWebSockets:

const uWS = require('uWebSockets.js');
const port = 9001;
const options = {
  key_file_name: 'key.pem',
  cert_file_name: 'cert.pem',
};
uWS.App(options)
  .ws('/*', {
    open: (socket) => {
      console.log('Client connected');
    },
    message: (socket, message, isBinary) => {
      console.log(`Received: ${message}`);
      socket.send(`You said: ${message}`, isBinary);
    },
    close: (socket, code, message) => {
      console.log('Client disconnected');
    },
  })
  .listen(port, (token) => {
    if (token) {
      console.log(`Listening on port ${port}`);
    } else {
      console.log(`Failed to listen on port ${port}`);
    }
  });
Enter fullscreen mode Exit fullscreen mode

5. Feathers

Feathers is a framework for NodeJS that allows you to create realtime microservice web applications. It features RESTful API,WebSockets (plug-in), and adaptable plugins that provide full control over your data, as well as communication and realtime updates via the Socket.IO module. With the Feathersjs/Socket.IO module, you can easily call service methods and receive realtime events via Socket.IO when working with Node.

The project has gained almost 15k GitHub stars and 26k npm weekly downloads. The Feathers library is widely known for its simplicity and ease of integration with various databases, and it also comes with excellent documentation to help you get started.

Pros of FeathersJs with Node

  • Lightweight and fast.
  • Works well with HTTP and WebSocket as it allows developers to use a single library for various types of communication in their applications.

Cons of FeatherJS with Node

  • FeatherJs' minimalist approach can pose limitations as apps grow. Adding numerous add-ons to build large-scale apps can lead to difficult management and maintenance.
  • Configuration may become complex to ensure it works properly as your app scales.

Getting started with FeathersJs

Run the following commands on your terminal.

sudo npm install -g @feathersjs/cli
mkdir my-app
cd my-app
feathers generate app
Enter fullscreen mode Exit fullscreen mode

Install the following libraries:

npm install feathers-memory
npm install @feathersjs/socketio
npm install @feathersjs/feathers
Enter fullscreen mode Exit fullscreen mode

If you run into permission errors, you can run the code below:

sudo chown -R $(whoami) ~/.npm

Enter fullscreen mode Exit fullscreen mode

Create an app.js file in the my-app directory and paste the code provided below into it.

const feathers = require('@feathersjs/feathers');
const socketio = require('@feathersjs/socketio');
const memory = require('feathers-memory');

// Create a Feathers application
const app = feathers();

// Configure the Socket.IO transport
app.configure(socketio());

// Create a channel that will handle the transportation of all realtime events
app.on('connection', connection => app.channel('everybody').join(connection));

// Publish all realtime events to the `everybody` channel
app.publish(() => app.channel('everybody'));

// To keep things simple, create a messages service and just store the messages in memory instead of a database
app.use('messages', memory());

// Start the server on port 3030
app.listen(3030);
Enter fullscreen mode Exit fullscreen mode

6. Faye-WebSocket

Faye WebSocket is a versatile WebSocket implementation derived from the Faye project. Faye is a messaging system that uses the Publish/Subscribe model and the Bayeux protocol. It provides message servers for Node, Ruby, and all major web browsers.

With Faye-WebSocket, you can easily create WebSocket servers and clients within Node. It doesn't function as a standalone WebSocket server itself. Instead, it's designed to assist in managing WebSocket connections within an existing Node application. In other words, it adds WebSocket capabilities to a Node app that serves other purposes.

Additionally, it provides an abstraction for managing one-way server-to-client EventSource connections that enable servers to supply data to clients. These connections are based on streaming HTTP responses and are easily accessible. You can use them on an open event to confirm the completion of the WebSocket handshake in any situation requiring passive data delivery alongside bidirectional WebSocket communication, like in stock trading applications.

Pros of Faye-WebSocket

  • Faye-WebSocket is straightforward to implement and use, making it accessible for developers.
  • It is compatible with a wide range of platforms, including browsers and server environments.
  • Faye-WebSocket is lightweight, adding minimal overhead to your applications.

Cons of Faye-WebSocket

  • It lacks advanced features such as automatic reconnection.
  • The community around Faye-WebSocket is smaller than some other WebSocket libraries, which may result in fewer resources and support.

Getting started with Faye-WebSocket

How to install Faye-WebSocket:

npm install faye-websocket
Enter fullscreen mode Exit fullscreen mode

Here is an example of a basic Websocket server with Faye-WebSocket:

// Import the necessary libraries
const WebSocketLibrary = require('faye-webSocket'); // Import the WebSocket library
const http = require('http'); // Import the HTTP module

// Create an HTTP server
const httpServer = http.createServer();

// Handle WebSocket upgrades
httpServer.on('upgrade', function(request, socket, body) {
  if (WebSocketLibrary.isWebSocket(request)) { // Check if the request is a WebSocket upgrade request
    const WebSocket = new WebSocketLibrary(request, socket, body); // Create a WebSocket instance

    // Event handler for incoming messages
    WebSocket.on('message', function(event) {
      WebSocket.send(event.data); // Send the received message back to the client
    });

    // Event handler for WebSocket closure
    WebSocket.on('close', function(event) {
      console.log('WebSocket closed with code:', event.code, 'and reason:', event.reason);
      WebSocket = null; // Clear the WebSocket reference
    });
  }
});

// Start the HTTP server and listen on port 8000
httpServer.listen(8000);
Enter fullscreen mode Exit fullscreen mode

7. Primus

Primus is a universal wrapper for realtime frameworks like WS, Faye, SockJs, and Engine.io. It is a lightweight wrapper that simplifies working with realtime frameworks by offering a single, low-level, and stream-compatible interface for both server and client. Primus operates independently of any realtime framework, ensuring it remains as lightweight as possible.

In other words, you'll need to add realtime libraries as dependencies yourself. This can be achieved by using the ‘require’ to call the node_module folders that match the dependencies you need.

var Primus = require('primus')
var http = require('http');
Enter fullscreen mode Exit fullscreen mode

Pros of Primus

  • Switching between realtime frameworks in Primus is easy with just one line of code. No need for API rewrites if your project requirements change or the framework fails.
  • The built-in reconnect feature uses a randomized exponential backoff algorithm to reduce server stress and ensure seamless reconnections.
  • Primus is smart enough to detect when users drop their internet connection and reconnect when they return online.
  • It uses custom parsers to encode and decode messages for efficient data handling, reducing development effort and potential errors. The feature allows easy switching between encoding formats, such as binary, providing flexibility and optimization options.

Cons of Primus

  • Primus strives to offer a consolidated platform for realtime communication protocols, which can lead to complications, particularly with complex functions or customized functionalities such as end-to-end encryption or preprocessing of messages before they are sent or received.
  • Primus can be challenging for new developers or those seeking a simpler WebSocket library due to its complex feature set and configuration requirements.
  • Although Primus has documentation and examples, its resources and tutorials are less extensive than popular libraries like WS and SockJS. It also has a smaller community than libraries, focusing solely on one realtime protocol,

Getting started with Primus

To try out the Primus framework, you must install Primus and the framework of your interest. In this example, we will create a WebSocket application using Primus and WS, where Primus will be wrapping the WS library. Also, it’s important to know that Primus needs to be "attached" to an HTTP compatible server. These include the built-in http and https servers.

Install the following libraries to use Primus in your application

npm install primus
npm install ws
Enter fullscreen mode Exit fullscreen mode

Creating a new Primus instance is relatively straightforward. Here is a simple implementation of a WebSocket server using Prismus:

'use strict';

// Import the Primus and HTTP modules
let CustomPrimus = require('primus');
let http = require('http');

// Create an HTTP server
let httpServer = http.createServer();

// Create a Primus WebSocket instance and attach it to the HTTP server
let primus = new CustomPrimus(httpServer, { transformer: 'WebSockets' });

// Event handler for when a WebSocket connection is established
primus.on('connection', function (socket) {

  // Event handler for when data is received from the WebSocket client
  socket.on('data', function handleMessage(message) {
    console.log('Received a new message:', message);

    // Send a response back to the WebSocket client
    socket.write({ ping: 'pong' });
  });
});

// Listen on port 8080 on the HTTP server
httpServer.listen(8080);
Enter fullscreen mode Exit fullscreen mode

8. SocketCluster

SocketCluster is a highly scalable HTTP and realtime server engine. With it, you can create multi-process servers that utilize all available CPU cores on a machine or instance. This helps to ensure that your backend remains functional, even if there are worker crashes.

SocketCluster enables client-server and group communication through Pub/Sub channels. It uses local area networks (LAN) to connect the cluster's components and can quickly reconnect after a failure or disconnect without data loss.It is an excellent choice for creating online multiplayer games and resilient and scalable chat systems.

Pros of SocketCluster

  • SocketCluster is easy to scale, and set up.
  • It is easy to build lightweight and efficient Pub/Sub channels using SocketCluster. You can create millions of unique channels without worrying about memory or CPU usage.
  • SocketCluster comes with a built-in RPC that makes it simple to implement remote procedure calls (RPC) in realtime applications. With this, developers can easily create and call remote functions between servers and clients, making it easier to develop features like realtime data synchronization without the need for customized RPC solutions.

Cons of SocketCluster

  • Documentation can be hard to read with little to no examples.
  • SocketCluster needs a minimum of three running servers (state, broker, worker).
  • Does not allow bidirectional broadcast of messages within connected groups. However, channels are supported, enabling senders to transmit messages to multiple subscribed recipients.
  • Load testing with tools like K6 is not easy.

Getting started with SocketCluster

To Install SocketCluster

npm install -g socketcluster

Enter fullscreen mode Exit fullscreen mode

Once you’re done installing, the ‘socketcluster create’ command will create a fresh SocketCluster installation. For example, ‘socketcluster create myApp’ will create a directory inside your current working directory called myApp.

socketcluster create myApp

Enter fullscreen mode Exit fullscreen mode

Once finished, navigate to myApp and immediately start your server:

 node server.js

Enter fullscreen mode Exit fullscreen mode

For server-side configuration, you can configure SocketCluster by editing code inside server.js. SocketCluster has over 30 options which you can change to suit your specific needs

Here is a simple basic server.js

var SocketCluster = require('socketcluster');
var socketCluster = new SocketCluster({ 
workers: 1, // Number of worker processes 
brokers: 1, // Number of broker processes
port: 8000, // The port number on which your server should listen 
appName: 'myapp', // A unique name for your app 

// Switch wsEngine to 'sc-uws' for a performance boost (beta) 
wsEngine: 'ws',
 workerController: __dirname + '/worker.js',
brokerController: __dirname + '/broker.js', 
rebootWorkerOnCrash: true });
Enter fullscreen mode Exit fullscreen mode

Scaling WebSockets with the Pub/Sub pattern

WebSockets have revolutionized how data is exchanged by enabling fast, two-way communication between clients and servers. However, having only WebSockets may not always be enough to meet the demands of modern, highly responsive applications. The Pub/Sub (Publish/Subscribe) pattern must be embraced to distribute realtime data at scale effectively.

The Pub/Sub pattern is a more efficient way for developers to send messages to multiple users. Instead of sending data to each recipient individually, a publisher sends the message to a channel. Subscribers who are interested in that channel receive the updates they need.

This approach is more streamlined and scalable because it decouples the sender (publisher) from the receiver (subscriber), allowing for the efficient distribution of messages to multiple recipients. It minimizes the need for direct point-to-point communication, making it easier to add new subscribers and scale the system horizontally to handle increased loads without major architectural changes.

Ably: An alternative to traditional WebSocket libraries

You have explored eight WebSocket libraries in search of the perfect one, each with its own strengths and quirks. However, scaling your realtime applications remains a challenge. This is where Ably enters the scene as the ultimate serverless solution. Ably is not just another WebSocket library but rather your gateway to effortless scalability.

Ably solves any problem of scalability, efficiency, and responsiveness by integrating the Pub/Sub model into your application's architecture, This means that you can focus on building your realtime applications while enjoying data integrity and minimal latency.

Ably is a platform that allows your WebSocket-based applications to easily handle thousands, or even millions, of simultaneous connections. This ensures that your users receive realtime updates in a reliable and timely manner. We provide features such as presence detection, message history, and channels catering to different use cases.

Try out Ably for free.

Top comments (0)