sockjs-client

Browser WebSocket emulation library that automatically falls back across streaming and polling transports for reliable realtime connections.

Library
npm
v1.6.1
8,506stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
77/100Good
Development Activity72
Maintenance48
Community88
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
75/100Good
Architecture78
Code Quality78
Innovation64
Learning Curve80

SockJS-client is a browser JavaScript library that provides a WebSocket-like API for building real-time, full-duplex communication channels between a browser and a web server. It closely follows the HTML5 WebSocket API, so code already written against native WebSocket largely works with SockJS with minimal changes.

Where it earns its keep is degraded-network and legacy-browser support: if a native WebSocket connection isn’t available — because of an old browser, a restrictive corporate proxy, or a middlebox that strips upgrade headers — SockJS transparently falls back to one of several streaming or polling transports (XHR streaming, EventSource, htmlfile, XHR/JSONP polling) while presenting the exact same event-driven interface. It requires a compatible server counterpart, most commonly SockJS-node, though implementations exist for many other server-side stacks including Spring, Tornado, and Actix.

What You Get

  • A WebSocket-like SockJS object with onopen/onmessage/onclose events matching the HTML5 WebSocket API
  • Automatic transport negotiation across native WebSockets, XHR/XDR streaming, EventSource, htmlfile, and JSONP polling
  • Cross-domain support out of the box, including cookie-based sticky sessions for load-balanced deployments
  • A configurable session/timeout model (sessionId, timeout, transports options) for tuning connection and reconnection behavior
  • iframe-wrapped variants of key transports for browsers with same-origin restrictions

Common Use Cases

  • Adding real-time features to apps that must support older browsers or IE-era corporate networks
  • Building a cross-domain messaging channel between a browser and a server behind restrictive proxies
  • Pairing with SockJS-node (or another SockJS server implementation) to give a Node.js backend a robust realtime transport
  • Integrating with frameworks like Spring’s built-in WebSocket fallback support that already speak the SockJS protocol

Under The Hood

Architecture The SockJS constructor in lib/main.js implements a small state machine (CONNECTING/OPEN/CLOSING/CLOSED) modeled on the W3C WebSocket spec. Before picking a transport it queries the server’s capabilities through an InfoReceiver (lib/info-receiver.js, lib/info-ajax.js, lib/info-iframe.js), then hands the result to filterToEnabled in lib/utils/transport.js to narrow the transport list registered in lib/transport-list.js down to what both browser and server support. Each transport module under lib/transport/ (websocket, xhr-streaming, xdr-streaming, eventsource, htmlfile, xhr-polling, xdr-polling, jsonp-polling) implements the same emitter-style contract (on('message'), once('close')), which lets main.js iterate through candidates via _connect() without knowing transport-specific details. Cross-origin variants are produced by decorating a transport with lib/transport/lib/iframe-wrap.js, which runs the real transport inside a sandboxed iframe and bridges events back via postMessage (lib/iframe-bootstrap.js, lib/facade.js). Events flow through a small custom EventTarget/Event implementation (lib/event/) rather than the DOM’s, keeping the library dependency-free in non-browser test environments.

Tech Stack The library is plain ES5 CommonJS JavaScript with no build-time framework dependency in its runtime code; production dependencies are limited to debug (namespaced logging), eventsource (polyfill), faye-websocket (used by the test server), inherits (prototype inheritance helper), and url-parse (a URL parser with consistent cross-browser behavior). Browser bundles are produced with Browserify plus a Gulp pipeline (gulpfile.js) that headers, renames, and minifies the output into dist/sockjs.min.js; a newer build script also produces an ESM bundle via esbuild. Cross-browser testing runs through Karma with karma-browserify, karma-chrome-launcher, and karma-browserstack-launcher for real-device coverage, while Node-side tests run under Mocha. engines requires Node >=12.

Code Quality The test suite is split across tests/node.js (Mocha, requiring tests/lib/main, main-node, utils, receivers, senders, end-to-end, transports, and utils-event in a deliberate order to avoid global side effects) and a browser bundle exercised via Karma/BrowserStack — giving the library both fast Node-side coverage and real cross-browser verification, which matters heavily for a transport-fallback library. ESLint is configured (.eslintrc, .jscsrc) and enforced via npm run lint, and GitHub Actions (.github/workflows/node.js.yml) runs CI. There is no TypeScript source, but a hand-maintained dist/sockjs.d.ts ships typed declarations for consumers. Error handling favors explicit, spec-shaped errors (SyntaxError, TypeError, and messages like InvalidAccessError/InvalidStateError) over silent failure, mirroring the native WebSocket API’s error semantics.

API Design The public surface deliberately mirrors the native WebSocket constructor and event model (new SockJS(url), .onopen, .onmessage, .send(), .close()), which minimizes the ramp-up for anyone who already knows WebSockets — most existing WebSocket client code needs only the constructor swapped. Extensions beyond the base spec are narrow and well-scoped: a transports allow-list, a configurable sessionId (fixed length or a custom generator function), a server prefix, and per-transport timeout/transportOptions. The library is explicit about a real constraint developers must design around — only one SockJS connection per domain is supported at a time — documenting the workaround (multiple subdomains) rather than hiding the limitation.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search