Native WebSocket Client in Node.js

Introduction

Node.js v21 introduced (see commit, PR and CHANGELOG) an enhancement to WebSocket API support by enabling a built-in WebSocket client by default. This change, derived from the Undici library, simplifies real-time communication for Node.js applications. The release Version 22.4.0 shows that the WebSocket API is now considered stable in Node v22 (commit and PR) and ready for production use, as per the project's documentation standards.

Native WebSocket Client

Node.js can now act as a WebSocket client without relying on external libraries like ws or socket.io for client connections. This allows Node.js applications to initiate and manage outgoing WebSocket connections directly, streamlining tasks such as connecting to real-time data feeds or interacting with other WebSocket servers. Users can now create a websocket client connection with the standard new WebSocket() constructor.

Building on the previous summary, let's add more practical examples to demonstrate the new WebSocket client functionality that demonstrates basic use-cases.

Basic Connection and Message Handling

// Creates a new WebSocket connection to the specified URL.
const socket = new WebSocket('ws://localhost:8080');

// Executes when the connection is successfully established.
socket.addEventListener('open', event => {
  console.log('WebSocket connection established!');
  // Sends a message to the WebSocket server.
  socket.send('Hello Server!');
});

// Listen for messages and executes when a message is received from the server.
socket.addEventListener('message', event => {
  console.log('Message from server: ', event.data);
});

// Executes when the connection is closed, providing the close code and reason.
socket.addEventListener('close', event => {
  console.log('WebSocket connection closed:', event.code, event.reason);
});

// Executes if an error occurs during the WebSocket communication.
socket.addEventListener('error', error => {
  console.error('WebSocket error:', error);
});

Sending and Receiving JSON Data

const socket = new WebSocket('ws://localhost:8080');

socket.addEventListener('open', () => {
  const data = { type: 'message', content: 'Hello from Node.js!' };
  socket.send(JSON.stringify(data));
});

socket.addEventListener('message', event => {
  try {
    const receivedData = JSON.parse(event.data);
    console.log('Received JSON:', receivedData);
  } catch (error) {
    console.error('Error parsing JSON:', error);
    console.log('Received data was:', event.data);
  }
});

The json code above demonstrates sending and receiving JSON data, which is common in WebSocket applications. It uses JSON.stringify() to convert JavaScript objects to JSON strings before sending. And converts the received string back to a JavaScript object with JSON.parse(). Finally, it includes error handling for JSON parsing.

This offers reduced dependency management and improved compatibility. Developers can avoid installing and maintaining additional WebSocket client libraries. The built-in implementation aligns with modern web standards, ensuring better interoperability. The enhancement focuses on the client-side of WebSocket communication, enabling Node.js to act as a WebSocket client.

Important to Understand

Node.js v22 does not provide a built-in native WebSocket server implementation. To create a WebSocket server that accepts incoming connections from web browsers or other clients, one still need to use libraries like ws or socket.io. This means that while Node.js can now easily connect to WebSocket servers, it still requires external tools to become a WebSocket server.

In Summary

Node.js v22 empowers applications to seamlessly interact with WebSocket servers as clients, but the creation of WebSocket servers within Node.js remains dependent on established libraries. This distinction is crucial for developers to understand when implementing real-time communication in their Node.js projects.