NATS WebSocket Client
nats.ws is a robust JavaScript and TypeScript client library designed for interacting with the NATS messaging system over WebSocket connections. It supports a variety of environments including modern web browsers, Deno, and Node.js (requiring a WebSocket shim for Node.js). The library is currently at version 1.30.3 and maintains a frequent release cadence, often aligning with updates to its underlying core client logic (NBC, which is derived from `nats.deno`). A key differentiating factor is its specialized focus on WebSocket connectivity and its tight integration with the NATS ecosystem. Users are advised that nats.ws is now considered an integrated component within the larger nats.js monorepo, and future development and major feature enhancements are primarily focused there. Comprehensive migration documentation is available for transitioning to nats.js.
Common errors
-
ReferenceError: WebSocket is not defined
cause Running `nats.ws` in a Node.js environment without a global `WebSocket` implementation (shim). The library expects a W3C-compatible WebSocket API.fixInstall a WebSocket library like `websocket` (`npm install websocket`) and shim it globally before importing `nats.ws`: `globalThis.WebSocket = require("websocket").w3cwebsocket;`. -
NatsError: Protocol error -1 (code: 1006)
cause This error (or similar 'NatsError: Could not connect to server', 'EOF') indicates that the client failed to establish a proper WebSocket connection to the NATS server. Common causes include an incorrect server URL, the NATS server not running, a firewall blocking the connection, or unexpected data during the handshake.fixVerify the NATS server URL and port are correct (including `ws://` or `wss://` protocol). Ensure the NATS server is running and accessible from the client. Check for any network or firewall rules that might be blocking the connection. -
Module not found: Can't resolve 'nats.ws/nats.js'
cause This error typically occurs in bundlers (e.g., Webpack, Rollup, Angular CLI) when `nats.ws` v1.6.0 or newer is used, but the import statement `import { connect } from 'nats.ws/nats.js';` (which was for older versions) is still present. Bundlers might also struggle with ESM/CJS resolution.fixFor `nats.ws` v1.6.0 and newer, change the import statement to `import { connect } from 'nats.ws';`. If the issue persists with bundlers, ensure your bundler is correctly configured to handle ESM exports and resolve the main entry point (e.g., by ensuring `module` field in `package.json` is respected).
Warnings
- breaking Version 1.30.2 introduced a breaking change for NATS Object Store. Objects 512MB and larger might require a migration strategy. Users should consult the `nats.deno` v1.29.2 release notes (linked from `nats.ws` v1.30.2 changelog) for detailed migration steps before updating to avoid data integrity issues.
- breaking Version 1.30.3 includes updates to support a change in JetStream behavior in `nats-server` v2.10.26 and beyond. This may affect applications using JetStream features with older server versions, potentially leading to unexpected behavior.
- deprecated The `nats.ws` project is now integrated into the `nats.js` monorepo. While `nats.ws` still receives maintenance updates, the primary development and new feature additions are concentrated in `nats.js`. Users are strongly encouraged to migrate to `nats.js` for new projects or existing ones to benefit from ongoing improvements and unified API.
- gotcha By default, `nats.ws` assumes `wss://` (secure WebSocket) for server addresses provided as `host:port` (e.g., `localhost:9222`). If connecting to an insecure `ws://` endpoint, the protocol must be explicitly specified in the server URL (e.g., `ws://localhost:9222`).
- gotcha When connecting to NATS clusters with mixed `ws://` and `wss://` protocols, or if using a proxy that might advertise incorrect server updates, you may need to set the `ignoreServerUpdates` connection option to `true`. Failure to do so might cause the client to attempt to connect to an incompatible endpoint.
- breaking The primary import path for modules like `connect` changed with `v1.6.0`. Prior to `v1.6.0`, the correct ESM import was `import { connect } from 'nats.ws/nats.js';`. For `v1.6.0` and later, it is simply `import { connect } from 'nats.ws';`.
Install
-
npm install nats.ws -
yarn add nats.ws -
pnpm add nats.ws
Imports
- connect
import { connect } from 'nats.ws/nats.js';import { connect } from 'nats.ws'; - StringCodec
import { StringCodec } from 'nats.ws/nats.js';import { StringCodec } from 'nats.ws'; - NatsConnection
import type { NatsConnection } from 'nats.ws';
Quickstart
import { connect, StringCodec, Empty } from 'nats.ws';
// In a Node.js environment, you might need to shim WebSocket:
// globalThis.WebSocket = require('websocket').w3cwebsocket;
async function runNatsClient() {
const servers = process.env.NATS_SERVER_URL ?? 'ws://localhost:9222';
console.log(`Connecting to NATS server at: ${servers}`);
try {
const nc = await connect({ servers: servers });
const sc = StringCodec.create();
console.log(`Connected to ${nc.getServer()}`);
// Subscribe to a subject and respond to requests
const sub = nc.subscribe('time.requests');
(async () => {
for await (const m of sub) {
const requestPayload = sc.decode(m.data);
const response = `Current time for '${requestPayload}': ${new Date().toLocaleTimeString()}`;
m.respond(sc.encode(response));
console.log(`[time.requests] received: '${requestPayload}' and responded with: '${response}'`);
}
console.log('Subscription to time.requests closed');
})();
// Publish a message and request a response
const requestPayload = 'What time is it in Tokyo?';
const response = await nc.request('time.requests', sc.encode(requestPayload), { timeout: 1000 });
console.log(`[time.requests] received response: ${sc.decode(response.data)}`);
// Publish a simple message
nc.publish('hello', sc.encode('world'));
console.log('Published "hello world" to subject "hello"');
await nc.flush(); // Ensure all messages are sent
await nc.close();
console.log('Connection closed.');
} catch (err: any) {
console.error(`Error connecting or interacting with NATS: ${err.message}`);
if (err.code) {
console.error(`NATS Error Code: ${err.code}`);
}
}
}
runNatsClient();