Skip to main content

WebSockets

High-performance WebSockets for React Native, built as a Nitro Module (libwebsockets + mbedTLS). This package lives alongside react-native-nitro-fetch in the same repo; HTTP stays in nitro-fetch, sockets in nitro-websockets.

Installation​

Install three packages: the WebSocket module, Nitro Modules (required by all Nitro libraries), and react-native-nitro-text-decoder (a peer dependency used to decode UTF-8 text frames).

npm i react-native-nitro-websockets react-native-nitro-text-decoder react-native-nitro-modules
tip

If you already use react-native-nitro-fetch, just add the websockets and text-decoder packages. Keep react-native-nitro-modules on a compatible version.

Then install native pods and rebuild:

cd ios && pod install && cd ..
npx react-native run-ios # or run-android

NitroWebSocket API​

The JS surface is a small class modeled after the browser WebSocket.

Constructor​

import { NitroWebSocket } from 'react-native-nitro-websockets';

const ws = new NitroWebSocket(
url: string,
protocols?: string | string[],
headers?: Record<string, string>
);
  • url — ws: / wss: endpoint
  • protocols — optional subprotocol string or list (Sec-WebSocket-Protocol)
  • headers — optional extra HTTP headers for the upgrade request

Properties​

PropertyTypeDescription
readyState'CONNECTING' | 'OPEN' | 'CLOSING' | 'CLOSED'Current connection state
urlstringThe WebSocket URL
protocolstringNegotiated subprotocol
bufferedAmountnumberBytes queued for sending
extensionsstringNegotiated extensions

Methods​

  • send(data: string | ArrayBuffer) — Send text or binary data
  • close(code?: number, reason?: string) — Close the connection (default code 1000)

Events​

ws.onopen = () => void;
ws.onmessage = (e: WebSocketMessageEvent) => void;
ws.onerror = (error: string) => void;
ws.onclose = (e: { code: number; reason: string }) => void;

The WebSocketMessageEvent contains:

  • e.data — string for text frames
  • e.isBinary — true for binary frames; use e.binaryData (ArrayBuffer)

Example​

const ws = new NitroWebSocket('wss://echo.websocket.org');

ws.onopen = () => console.log('open');
ws.onmessage = (e) => console.log('message', e.data, e.isBinary);
ws.onerror = (err) => console.error(err);
ws.onclose = (e) => console.log('closed', e.code, e.reason);

ws.send('hello');
ws.close(1000, 'bye');

Prewarm on next app launch​

Prewarming starts the TLS/WebSocket handshake natively on startup (before JS runs), using URLs you enqueue from JavaScript.

note

Prewarm uses the same NativeStorage queue as nitro-fetch, so react-native-nitro-fetch must be installed.

JS helpers​

import {
prewarmOnAppStart,
removeFromPrewarmQueue,
clearPrewarmQueue,
} from 'react-native-nitro-websockets';

// Queue or update an entry (deduped by URL)
prewarmOnAppStart('wss://api.example.com/ws', ['chat-v1'], {
Authorization: 'Bearer ...',
});

// Remove one URL from the queue
removeFromPrewarmQueue('wss://api.example.com/ws');

// Clear the entire queue
clearPrewarmQueue();

Android native hook​

In Application.onCreate, before or after loadReactNative:

import com.margelo.nitro.nitrofetchwebsockets.NitroWebSocketAutoPrewarmer

override fun onCreate() {
super.onCreate()
NitroWebSocketAutoPrewarmer.prewarmOnStart(this)
// ...
}

Expo Plugin (Android)​

If you use Expo, the plugin automatically injects NitroWebSocketAutoPrewarmer.prewarmOnStart() into MainApplication.kt during expo prebuild — no manual native code changes needed.

Add to your app.json:

{
"plugins": ["react-native-nitro-websockets"]
}

Auth on cold start​

If prewarmed sockets need fresh headers, register token refresh with target: 'websocket' or 'all' using registerTokenRefresh from react-native-nitro-fetch. See the Token Refresh guide for details.

iOS transport​

On iOS, connections run on a client built on Network.framework, which reads the socket in bulk and frames messages in-process. It is much faster for bursts of messages than NSURLSessionWebSocketTask. Setting NitroWebSocketsUseNetworkFramework to false in Info.plist switches back to NSURLSessionWebSocketTask, which you need for App Transport Security, NSPinnedDomains pinning, proxies or HTTP authentication.

<key>NitroWebSocketsUseNetworkFramework</key>
<false/>

With Expo, set it under ios.infoPlist in the app config.

App Transport Security does not apply to Network.framework, so ws:// connects to any host and NSPinnedDomains pinning is not applied. wss:// connections still validate the server certificate against the system trust store, and redirects from wss:// to ws:// are refused.

Other differences from NSURLSessionWebSocketTask:

  • the system HTTP or PAC proxy may not be used
  • user:pass@ credentials and 401 challenges are not handled
  • the handshake sends no Accept, Accept-Language or Accept-Encoding header
  • messages can be up to 16 MB instead of 1 MB
  • if the server does not answer close() within 5 seconds, onclose fires with code 1006
  • a close frame with a reserved code or a reason that is not valid UTF-8 fails the connection: onerror, then onclose with 1006
  • a failed send does not fire onerror by itself; the connection failing does
  • network changes are not watched and no TCP keepalives are sent, so an idle connection can stay open after the network changes until a read or write fails

See also​