@stomp/stompjs vs sockjs-client vs stompjs
Real-Time Messaging Architectures: STOMP Clients and SockJS Transports
@stomp/stompjssockjs-clientstompjsSimilar Packages:

Real-Time Messaging Architectures: STOMP Clients and SockJS Transports

@stomp/stompjs, sockjs-client, and stompjs address real-time communication in web applications, but they operate at different layers of the network stack. @stomp/stompjs is the modern, actively maintained client for the STOMP (Simple Text Oriented Messaging Protocol), enabling structured message exchange over WebSocket or other transports. sockjs-client provides a browser-side transport layer that mimics the WebSocket API but offers fallback mechanisms (like XHR streaming) for environments where raw WebSockets are blocked or unstable. stompjs refers to the legacy, unscoped version of the STOMP client, which is largely superseded by the scoped @stomp/stompjs package. Together, these tools allow developers to build robust chat systems, live dashboards, and collaborative features, though choosing the right combination depends on server capabilities and browser compatibility requirements.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
@stomp/stompjs0887473 kB277 months agoApache-2.0
sockjs-client08,506700 kB31-MIT
stompjs01,446-8812 years agoApache-2.0

Real-Time Messaging Architectures: STOMP Clients and SockJS Transports

Building real-time features like chat, notifications, or live trading dashboards requires a solid understanding of how messages move between client and server. The packages @stomp/stompjs, sockjs-client, and stompjs often appear together in this space, but they solve different problems. @stomp/stompjs and stompjs handle the application-level messaging protocol (STOMP), while sockjs-client handles the underlying network transport. Let's break down how they differ and how to architect your connection layer correctly.

🏗️ Protocol vs. Transport: Knowing the Difference

The most common confusion is treating STOMP and SockJS as interchangeable. They are not. STOMP is a messaging protocol (like HTTP) that defines how messages are framed and routed. SockJS is a transport layer (like TCP) that defines how bytes move over the network.

@stomp/stompjs implements the STOMP protocol. It expects a transport layer to send raw frames.

// @stomp/stompjs: Requires a transport (WebSocket or SockJS)
import { Client } from '@stomp/stompjs';

const client = new Client({
  brokerURL: 'wss://example.com/stomp',
  connectHeaders: { login: 'user', passcode: 'secret' },
  onConnect: () => console.log('Connected via STOMP')
});
client.activate();

sockjs-client implements the SockJS transport protocol. It does not understand STOMP frames on its own.

// sockjs-client: Pure transport, no STOMP logic
import SockJS from 'sockjs-client';

const socket = new SockJS('https://example.com/sockjs');
socket.onopen = () => console.log('Transport Open');
socket.send('Raw string data'); // No STOMP framing

stompjs (legacy) also implements STOMP but uses an older API style and lacks modern maintenance.

// stompjs (legacy): Older API style
import Stomp from 'stompjs';

const client = Stomp.over(new WebSocket('wss://example.com/stomp'));
client.connect('user', 'secret', () => console.log('Connected'));

🛠️ Maintenance Status: Modern vs. Legacy

Choosing the right package starts with checking if it is still alive. The ecosystem has shifted significantly toward the scoped npm package.

@stomp/stompjs is the current standard. It is rewritten in TypeScript, supports module imports, and receives regular updates for bug fixes and STOMP 1.2 compliance.

// @stomp/stompjs: Modern ES6 imports and class-based API
import { Client, Frame } from '@stomp/stompjs';

const client = new Client({
  brokerURL: 'wss://example.com/stomp',
  onMessage: (frame) => console.log(frame.body)
});

stompjs (unscoped) is effectively deprecated for new work. While it might still function, it lacks the architectural improvements of its successor and may not handle edge cases in modern browsers correctly.

// stompjs (legacy): Callback-heavy API
import Stomp from 'stompjs';

// No class instantiation, uses global-like object
Stomp.debug = true; 
const client = Stomp.client('wss://example.com/stomp');

sockjs-client remains stable. Since it solves a specific compatibility problem (WebSocket fallbacks), its API surface hasn't needed major changes. It is safe to use if your server demands it.

// sockjs-client: Stable event emitter API
import SockJS from 'sockjs-client';

const socket = new SockJS('/sockjs');
socket.onmessage = (e) => console.log(e.data);

🔌 Transport Flexibility: WebSocket vs. SockJS Fallback

One of the strongest features of @stomp/stompjs is its ability to swap transports. You can use native WebSockets for performance or sockjs-client for compatibility without changing your STOMP logic.

@stomp/stompjs with Native WebSocket (Recommended for modern browsers)

// @stomp/stompjs: Direct WebSocket transport
import { Client } from '@stomp/stompjs';

const client = new Client({
  brokerURL: 'wss://example.com/stomp',
  // Uses native WebSocket by default
});

@stomp/stompjs with SockJS (For restrictive networks)

// @stomp/stompjs: Injecting SockJS as transport
import { Client } from '@stomp/stompjs';
import SockJS from 'sockjs-client';

const client = new Client({
  brokerURL: 'https://example.com/sockjs',
  webSocketFactory: () => new SockJS('https://example.com/sockjs'),
});

sockjs-client Standalone (Without STOMP)

// sockjs-client: Raw transport only
import SockJS from 'sockjs-client';

// You must handle your own message framing
const socket = new SockJS('/sockjs');
socket.send(JSON.stringify({ type: 'EVENT', payload: {} }));

🔄 Connection Lifecycle and Reconnection

Real-world networks are unstable. Handling disconnects gracefully is critical for user experience. The libraries handle this differently.

@stomp/stompjs has built-in reconnection logic. You configure it once, and it handles the retry loop automatically.

// @stomp/stompjs: Built-in reconnection config
const client = new Client({
  brokerURL: 'wss://example.com/stomp',
  reconnectDelay: 5000, // Retry every 5 seconds
  onDisconnect: () => console.log('Disconnected, retrying...')
});

stompjs (legacy) requires manual reconnection handling. You must write the retry logic yourself inside the disconnect callback.

// stompjs (legacy): Manual reconnection
const client = Stomp.over(ws);
client.onclose = () => {
  setTimeout(() => connectAgain(), 5000); // Custom logic needed
};

sockjs-client has its own reconnection for the transport layer, but it doesn't know about application-level heartbeats.

// sockjs-client: Transport level reconnect
const socket = new SockJS('/sockjs');
socket.onclose = () => console.log('Transport closed'); 
// Does not handle STOMP heartbeat timeouts

📡 Subscriptions and Message Handling

How you listen for messages defines the structure of your frontend code. STOMP provides a topic-based subscription model, while raw SockJS is just a stream of data.

@stomp/stompjs uses subscription IDs and headers for robust message routing.

// @stomp/stompjs: Structured subscription
const subscription = client.subscribe('/topic/messages', (message) => {
  console.log(`Received: ${message.body}`);
});
// Later: subscription.unsubscribe();

stompjs (legacy) uses a similar model but with a callback-based return value.

// stompjs (legacy): Callback subscription
const sub = client.subscribe('/topic/messages', (message) => {
  console.log(`Received: ${message.body}`);
});

sockjs-client has no concept of topics. You receive every message sent to the connection and must filter manually.

// sockjs-client: Manual message filtering
socket.onmessage = (e) => {
  const data = JSON.parse(e.data);
  if (data.destination === '/topic/messages') {
    console.log(`Received: ${data.body}`);
  }
};

🛡️ Security and Headers

Authentication in real-time apps often happens during the connection handshake. STOMP supports headers for this, while raw SockJS relies on cookies or URL params.

@stomp/stompjs allows secure header injection during connect.

// @stomp/stompjs: Secure connect headers
const client = new Client({
  brokerURL: 'wss://example.com/stomp',
  connectHeaders: {
    Authorization: `Bearer ${accessToken}`
  }
});

stompjs (legacy) supports headers but with a slightly different argument signature.

// stompjs (legacy): Connect with headers
client.connect({ login: 'user', passcode: 'secret' }, onConnect);

sockjs-client does not support custom headers on the WebSocket handshake due to browser limitations. You must use cookies or query parameters.

// sockjs-client: No custom headers on handshake
// Auth must be via Cookie or URL query param
const socket = new SockJS('https://example.com/sockjs?token=xyz');

📊 Summary: Key Differences

Feature@stomp/stompjssockjs-clientstompjs (Legacy)
LayerApplication (STOMP Protocol)Transport (Network)Application (STOMP Protocol)
Status✅ Active & Maintained✅ Stable⚠️ Legacy / Deprecated
TransportWebSocket or SockJSSockJS (XHR/WebSocket)WebSocket
API StyleModern Class-basedEvent EmitterCallback-based Object
ReconnectionBuilt-in ConfigurationTransport Level OnlyManual Implementation
TypeScript✅ First-class Support⚠️ Community Types❌ Minimal Support

💡 Architectural Recommendation

For most modern applications, the ideal setup is @stomp/stompjs over native WebSockets. This gives you the structure of STOMP with the performance of standard WebSockets.

// Recommended Architecture
import { Client } from '@stomp/stompjs';

const client = new Client({
  brokerURL: 'wss://api.example.com/stomp',
  reconnectDelay: 5000,
  onConnect: () => {
    client.subscribe('/user/queue/notifications', handleNotification);
  }
});
client.activate();

Only introduce sockjs-client if your infrastructure team mandates SockJS for load balancer compatibility or if you must support very old browsers that lack WebSocket support.

// Fallback Architecture
import { Client } from '@stomp/stompjs';
import SockJS from 'sockjs-client';

const client = new Client({
  brokerURL: 'https://api.example.com/sockjs',
  webSocketFactory: () => new SockJS('https://api.example.com/sockjs'),
});

Avoid stompjs (unscoped) entirely. There is no technical benefit to using the legacy package, and it introduces risk due to lack of maintenance. Migrating to @stomp/stompjs is usually a straightforward refactor that future-proofs your real-time features.

How to Choose: @stomp/stompjs vs sockjs-client vs stompjs

  • @stomp/stompjs:

    Choose @stomp/stompjs for all new projects requiring STOMP protocol support. It is the actively maintained, TypeScript-ready version that supports STOMP 1.2 and offers flexible transport configuration. It is the direct successor to the legacy stompjs package and provides better error handling, reconnection logic, and modern JavaScript features.

  • sockjs-client:

    Choose sockjs-client only if your backend server explicitly requires SockJS transport emulation. It is not a STOMP client itself but a transport layer that can be paired with @stomp/stompjs. Use it when you need to support older browsers or network environments that block standard WebSocket connections.

  • stompjs:

    Do NOT choose stompjs (unscoped) for new development. This package is considered legacy and is no longer actively maintained compared to @stomp/stompjs. Migrating to the scoped @stomp/stompjs package ensures access to security patches, modern API patterns, and community support.

README for @stomp/stompjs

STOMP.js

Build Status - Firefox, Chrome Build Status - Safari, Edge Node.js Tests API Docs Refresh

STOMP.js is a fully-fledged STOMP over WebSocket library for browsers and Node.js, providing seamless integration with STOMP protocol-compliant messaging brokers.

Table of Contents

Introduction

This library enables clients to connect to STOMP brokers over WebSocket (or TCP). It fully implements the STOMP protocol specifications (v1.0, v1.1, and v1.2), making it compatible with any broker that supports STOMP or STOMP over WebSocket.

Popular brokers like RabbitMQ, ActiveMQ, and others provide support for STOMP and STOMP over WebSockets out-of-the-box.

Features

  • Simple and intuitive API for interacting with the STOMP protocol
  • Support for STOMP protocol versions: 1.2, 1.1, and 1.0
  • Support for fallback options when WebSocket is unavailable
  • Supports both browser and Node.js environments
  • Option to connect using STOMP over TCP
  • Full support for binary payloads
  • Compatible with RxJS for reactive programming

Getting Started

This section provides a quick guide to integrating STOMP.js into your browser or Node.js application.

Browser

To use STOMP.js in a browser:

  1. Add the following in your HTML file:

    <script type="importmap">
      {
        "imports": {
          "@stomp/stompjs": "https://ga.jspm.io/npm:@stomp/stompjs@7.0.0/esm6/index.js"
        }
      }
    </script>
    <script
      async
      src="https://ga.jspm.io/npm:es-module-shims@1.5.1/dist/es-module-shims.js"
      crossorigin="anonymous"
    ></script>
    
  2. Use the library:

    import { Client } from '@stomp/stompjs';
    
    const client = new Client({
      brokerURL: 'ws://localhost:15674/ws',
      onConnect: () => {
        client.subscribe('/topic/test01', message =>
          console.log(`Received: ${message.body}`)
        );
        client.publish({ destination: '/topic/test01', body: 'First Message' });
      },
    });
    
    client.activate();
    

Node.js

To use STOMP.js in a Node.js environment:

  1. Install the package:

    npm install @stomp/stompjs ws
    
  2. Use it in your application:

    import { Client } from '@stomp/stompjs';
    
    import { WebSocket } from 'ws';
    Object.assign(global, { WebSocket });
    
    const client = new Client({
      brokerURL: 'ws://localhost:15674/ws',
      onConnect: () => {
        client.subscribe('/topic/test01', message =>
          console.log(`Received: ${message.body}`)
        );
        client.publish({ destination: '/topic/test01', body: 'First Message' });
      },
    });
    
    client.activate();
    

Documentation

Comprehensive documentation can be found at: STOMP.js Documentation

Upgrading

If you are updating from an older version of STOMP.js, review the Upgrading Guide for any required changes.

Usage with RxJS

Rx-Stomp builds upon this library, exposing all its features as RxJS Observables, enabling reactive programming patterns.

TypeScript Support

STOMP.js includes built-in TypeScript definitions, eliminating the need for external type definition files. Begin coding with TypeScript out-of-the-box!

Changelog

Visit the Change Log for information about changes, improvements, and fixes in recent releases.

Contributing

Thinking of contributing to STOMP.js? Great! To get started:

  • Read the Contributing Guide for development instructions.
  • Report bugs or suggest features by creating an issue on GitHub.

We welcome contributions from the community!

Authors

This library is made possible by these amazing contributors:

This library is originally based on stompjs by Jeff Mesnil with enhancements and bug fixes from Jeff Lindsay and Vanessa Williams.

License

Licensed under the Apache-2.0 License. See the LICENSE file for details.