reconnecting-websocket
A drop-in WebSocket wrapper for Web, Node.js, and React Native that auto-reconnects with configurable backoff and message buffering.
Repository Health
Technical Analysis
reconnecting-websocket is a small, dependency-free wrapper around the native WebSocket API that transparently reconnects a dropped connection instead of leaving the caller to detect and recover from disconnects manually. It exposes the exact same interface as the browser’s WebSocket object — same methods, same Level0/Level2 event model, same readyState constants — so it can be swapped in as a drop-in replacement with no changes to surrounding code.
Under the hood it tracks connection attempts with an exponential backoff (configurable min/max delay and growth factor), enforces a connection timeout so a hung handshake doesn’t stall forever, and treats a connection as “stable” only after it has stayed open past a minimum uptime — resetting the retry counter at that point rather than after every successful open. Messages sent while disconnected are queued (up to a configurable cap) and flushed in order once the connection re-opens, so callers don’t have to buffer outgoing data themselves.
Because it takes an injectable WebSocket constructor, the same library works in a browser, inside a Service Worker, in Node.js (paired with the ws package), or in React Native — anywhere a WebSocket-shaped constructor is available. The URL can also be a synchronous or async provider function, which supports round-robin server selection or fetching a fresh auth token before each reconnection attempt.
What You Get
- A WebSocket-compatible class with the same methods, properties, and Level0/Level2 event model as the native WebSocket, so it can replace
new WebSocket(...)with no other code changes - Automatic reconnection with configurable exponential backoff (min/max delay, growth factor) and a connection timeout that aborts hung handshakes
- A minimum-uptime check that only resets the retry counter once a connection has proven stable, avoiding tight reconnect loops against a flapping server
- Message buffering that enqueues
send()calls made while disconnected (up to a configurable cap) and flushes them in order once the socket reopens - Support for static, synchronous, or async URL providers, enabling round-robin endpoint selection or fetching a fresh token before each connection attempt
- An injectable WebSocket constructor option, making the library usable in Node.js (with the
wspackage), Service Workers, and React Native, not just browsers
Common Use Cases
- Keeping a real-time dashboard or chat UI connected to a backend WebSocket server across flaky networks or brief server restarts
- Running a persistent WebSocket connection from a Node.js service or CLI tool using the
wspackage as the underlying implementation - Maintaining a live connection in a React Native app where network transitions (Wi-Fi to cellular, backgrounding) frequently drop sockets
- Rotating between multiple WebSocket endpoints with a round-robin URL provider for simple client-side load distribution
- Reconnecting with a freshly fetched auth token on each attempt via an async URL provider, for APIs that require per-connection authentication
Under The Hood
Architecture
The library is a single class, ReconnectingWebSocket (in reconnecting-websocket.ts), that composes over a real WebSocket instance rather than extending it: _connect() resolves the URL (sync, string, or async provider), instantiates the underlying WebSocket, and wires _handleOpen/_handleMessage/_handleError/_handleClose handlers that call back into the class’s own listener maps and public on* callbacks. Reconnection is driven entirely by state flags (_connectLock, _shouldReconnect, _closeCalled) and two timers (_connectTimeout, _uptimeTimeout) rather than a formal state machine, keeping the control flow compact but meaning correctness depends on careful ordering of flag resets across close(), reconnect(), and the error/close handlers. A companion events.ts module defines lightweight Event/ErrorEvent/CloseEvent classes so the library doesn’t depend on the DOM’s Event constructor, which is what keeps it usable outside a browser (Node.js, React Native). What breaks if this abstraction changes: any consumer relying on exact native WebSocket event shapes would need the custom event classes to keep tracking the same fields.
Tech Stack
Written in strict TypeScript (tsconfig.json targets ES5 with dom/es6 libs) and built with Rollup (rollup-plugin-typescript2) into IIFE, AMD, CommonJS, and ES module bundles, then minified with uglify-es for the browser build. It has zero runtime dependencies ("dependencies": {} in package.json) — the only dependency-shaped input is an injectable WebSocket constructor supplied by the caller, commonly the ws package in Node.js. Linting runs through eslint with @typescript-eslint, formatting through prettier, and Git hooks are enforced with husky + lint-staged on commit.
Code Quality
Tests live in __tests__/test.ts (via Jest with ts-jest) and are extensive — over 800 lines covering constructor validation, backoff timing, message buffering, timeout handling, and reconnect/close semantics against a real local ws server rather than mocks, plus a companion unresponsive-server.js fixture for exercising the connection-timeout path. Coverage is collected with jest --coverage and reported to Coveralls in CI. Error handling is explicit throughout (throw Error(...) for invalid WebSocket constructors or malformed URLs, guarded try/catch around socket teardown), and the codebase is fully typed with strict: true enabled.
What Makes It Unique
Its main differentiator is scope discipline: rather than building a general real-time abstraction (channels, pub/sub, protocol framing), it solves exactly one problem — reconnection — while staying byte-for-byte compatible with the native WebSocket API, so it can be dropped into existing code with a single import change. The injectable-constructor design is what lets the same small library serve browsers, Node.js, Service Workers, and React Native without separate platform builds.
Used by 2 apps in this directory
GitButler
Developer Tools · Devops · AI Development
Git, but better — a modern version control client with stacked branches, parallel workflows, unlimited undo, and first-class support for AI-powered development.
Teable
Databases · No Code Platforms
A no-code PostgreSQL database with spreadsheet UX, real-time collaboration, and native AI agents — built for teams that outgrow Airtable.