SignalR
The official JavaScript/TypeScript client for ASP.NET Core SignalR, giving browser and Node apps real-time, bidirectional connections to .NET Hubs.
Repository Health
Technical Analysis
@microsoft/signalr is the official JavaScript and TypeScript client for ASP.NET Core SignalR, Microsoft’s real-time communication framework. It lets browser, Node.js, and web-worker clients open a persistent connection to a server-side Hub and both invoke server methods and receive server-pushed events, negotiating the best available transport (WebSockets, Server-Sent Events, or long polling) without any app code needing to know which one was chosen.
The client ships as part of the dotnet/aspnetcore monorepo (src/SignalR/clients/ts/signalr) but is published and consumed independently via npm, and is built to run identically across browser <script> tags, WebWorkers, and Node.js. It handles the SignalR handshake, hub protocol negotiation (JSON by default, MessagePack via a companion package), automatic reconnection with configurable backoff, and — in newer versions — stateful reconnect, which buffers and replays in-flight messages across a dropped connection so calls aren’t silently lost.
Because it targets the same wire protocol as the official .NET, Java, and other SignalR clients, it’s the natural choice whenever the backend is (or could be) ASP.NET Core and the frontend needs push notifications, live dashboards, chat, or collaborative features without hand-rolling a WebSocket protocol and reconnection logic from scratch.
What You Get
HubConnectionBuilderfor fluent connection configuration (URL, transport, protocol, logging, reconnect policy) andHubConnectionfor invoking server methods, streaming, and subscribing to server-pushed events- Automatic transport negotiation and fallback across WebSockets, Server-Sent Events, and long polling, so the same client code works across browsers and network conditions
- Built-in automatic reconnection with a configurable
IRetryPolicy, plus stateful reconnect that buffers unacknowledged messages so in-flight invocations survive a dropped connection - Pluggable hub protocols — JSON by default, with a companion
@microsoft/signalr-protocol-msgpackpackage for binary MessagePack framing on high-throughput connections - Support for server-to-client streaming (
IStreamResult) and client-to-server upload streams viaSubject, plus bearer-token authentication hooks including mid-connection token refresh
Common Use Cases
- Live dashboards and monitoring UIs that need server-pushed metric or status updates without polling
- Chat and messaging features backed by an ASP.NET Core Hub, shared across web, mobile, and desktop clients on the same protocol
- Collaborative editing or multi-user features (cursors, presence, live document state) that need low-latency bidirectional updates
- Progress and notification streaming for long-running server operations (file processing, background jobs) back to the initiating browser session
- Real-time gaming or IoT telemetry front ends where WebSocket-first with automatic long-polling fallback is required for restrictive networks
Under The Hood
Architecture
The client is layered around three collaborating pieces: HttpConnection (in HttpConnection.ts) owns the negotiate handshake and picks a concrete ITransport implementation (WebSocketTransport, ServerSentEventsTransport, or LongPollingTransport), HubConnection (in HubConnection.ts) sits above it and speaks the SignalR Hub protocol — tracking invocation IDs, dispatching server-to-client method calls to registered handlers, and driving the connection state machine (Disconnected → Connecting → Connected → Reconnecting) — and HandshakeProtocol/IHubProtocol implementations (JsonHubProtocol, with MessagePack in a sibling package) handle wire-format (de)serialization. Reconnection is layered in via DefaultReconnectPolicy and, for stateful reconnect, MessageBuffer, which tracks sequence IDs and acks so buffered invocations can be replayed after a transport swap; a change to the core IConnection/ITransport contract would ripple through every transport and the reconnect buffer, but the negotiate/transport/protocol layers stay cleanly separated from each other.
Tech Stack
The package is authored in strict TypeScript, compiled to three separate targets from one tsconfig.json — ESM (dist/esm), CommonJS (dist/cjs), and a UMD browser/webworker bundle built with webpack-cli — so the same source ships for import, require, and <script> consumption. Runtime dependencies are deliberately minimal and environment-shim-focused: abort-controller and node-fetch/eventsource polyfill browser fetch/EventSource APIs under Node, fetch-cookie handles cookie-jar behavior for Node-based long polling, and ws backs the Node WebSocket transport; the package has sideEffects: false for clean tree-shaking in bundlers.
Code Quality
The tests/ directory has one spec file per transport and protocol concern (WebSocketTransport.test.ts, LongPollingTransport.test.ts, ServerSentEventsTransport.test.ts, HubConnection.test.ts, HubConnection.Reconnect.test.ts, JsonHubProtocol.test.ts, and dedicated MessageSize/OutputSize tests), backed by hand-written Test* doubles (TestConnection, TestHttpClient, TestWebSocket) rather than a mocking framework, giving fine control over transport-level edge cases like partial reads and abrupt disconnects. The source is strict TypeScript throughout with an ESLint config extended from a shared monorepo ruleset, extensive TSDoc comments on every public type (@internal/@private annotations mark implementation-only surface), and defensive Arg runtime checks on public entry points; error handling favors typed custom errors (AbortError, HttpError, FailedToNegotiateWithServerError) over generic throws.
What Makes It Unique
What distinguishes this client from a typical WebSocket wrapper is that it implements a full application-level RPC and pub/sub protocol on top of whichever transport gets negotiated — the same Hub protocol also implemented by the .NET, Java, and other official SignalR clients — so method invocation, streaming, and cancellation semantics are identical regardless of transport or platform. Stateful reconnect (via MessageBuffer’s sequence/ack tracking) is a comparatively rare capability among realtime client libraries: most WebSocket clients simply drop in-flight messages on disconnect, while this one can buffer and safely replay them once a new connection is established.