Receber por email
← Voltar para o catálogo

web-realtime-websockets

Native WebSocket API patterns, connection lifecycle, reconnection strategies, heartbeat, message typing, binary data, custom hooks

11estrelas
Atualizado há 7 meses

Ver no GitHub ↗ Licença: MIT

Como adicionar

/plugin marketplace add agents-inc/skills

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/web-realtime-websockets/svg)](https://www.skillteca.com.br/skills/web-realtime-websockets)

Skills relacionadas

Ver todas de Dados e Análise →

Alerta por categoria

Receba novas skills de Dados e Análise toda segunda

1 email curto, só com as skills novas de Dados e Análise. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

WebSocket Real-Time Communication Patterns

Quick Guide: Use native WebSocket API for real-time bidirectional communication. Implement exponential backoff with jitter for reconnection. Use discriminated unions for type-safe message handling. Queue messages during disconnection for delivery on reconnect. Close connections on pagehide to allow bfcache.

<critical_requirements>

CRITICAL: Before Using This Skill

All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering, import type, named constants)

(You MUST implement exponential backoff with jitter for ALL reconnection logic)

(You MUST use discriminated unions with a type field for ALL WebSocket message types)

(You MUST queue messages during disconnection and flush on reconnect)

(You MUST implement heartbeat/ping-pong to detect dead connections)

(You MUST set binaryType to 'arraybuffer' when handling binary data)

(You MUST use wss:// for secure origins - browsers block ws:// on HTTPS pages except localhost)

(You MUST handle bfcache with pagehide/pageshow events)

</critical_requirements>

Auto-detection: WebSocket, ws://, wss://, onmessage, onopen, onclose, onerror, reconnect, heartbeat, ping, pong, real-time, bidirectional

When to use:

  • Building real-time features (chat, notifications, live updates)
  • Implementing bidirectional communication between client and server
  • Creating live dashboards or collaborative editing features
  • Streaming data updates with low latency requirements

When NOT to use:

  • One-way server-to-client streaming only (use SSE instead)
  • Simple request-response patterns (use HTTP/REST instead)
  • When library abstractions are required (use a WebSocket wrapper library)
  • When automatic backpressure handling is critical (consider WebSocketStream when widely supported)

Key patterns covered:

  • WebSocket connection lifecycle management
  • Reconnection with exponential backoff and jitter
  • Heartbeat/ping-pong for connection health
  • Message queuing during disconnection
  • Type-safe message handling with discriminated unions
  • Binary data handling (ArrayBuffer, Blob)
  • Custom React hooks (useWebSocket)
  • Authentication patterns
  • Room/channel subscriptions
  • bfcache compatibility

Detailed Resources:

  • [examples/core.md](examples/core.md) - Connection lifecycle, reconnection, heartbeat, queuing, auth, rooms, hooks
  • [examples/state-machine.md](examples/state-machine.md) - Connection state machine pattern
  • [examples/binary.md](examples/binary.md) - Binary data and file upload
  • [examples/presence.md](examples/presence.md) - User presence detection
  • [reference.md](reference.md) - Decision frameworks, close codes, anti-patterns

<philosophy>

Philosophy

WebSockets provide full-duplex communication channels over a single TCP connection, enabling real-time bidirectional data flow between client and server. Unlike HTTP, WebSocket connections remain open, eliminating the overhead of repeated handshakes.

The native WebSocket API is simple but requires careful handling:

  1. Connection Resilience: Networks are unreliable. Always implement reconnection with exponential backoff and jitter to prevent thundering herd problems.
  1. Connection Health: Intermediate proxies and firewalls can silently drop idle connections. Heartbeats detect dead connections and keep connections alive.
  1. Message Integrity: Messages sent during disconnection are lost. Queue them and flush on reconnect for reliable delivery.
  1. Type Safety: WebSocket messages are untyped strings. Use discriminated unions with a shared type field for compile-time safety.
  1. bfcache Compatibility: Open WebSocket connections prevent pages from using the browser's back/forward cache, degrading navigation performance. Close connections on pagehide and reconnect on pageshow when event.persisted.

Connection Lifecycle:

CONNECTING -> OPEN <-> (messages) -> CLOSING -> CLOSED
                 |                      |
             (error) <- reconnect <- (close)

</philosophy>

<patterns>

Core Patterns

Pattern 1: Basic WebSocket Connection

The native WebSocket API provides four lifecycle events: onopen, onmessage, onerror, and onclose. Always handle all four.

const WS_URL = "wss://api.example.com/ws";
const socket = new WebSocket(WS_URL);

socket.onopen = () => {
  /* connection ready - safe to send */
};
socket.onmessage = (event: MessageEvent) => {
  /* JSON.parse(event.data) */
};
socket.onerror = (event: Event) => {
  /* always followed by onclose */
};
socket.onclose = (event: CloseEvent) => {
  /* reconnect here */
};

Why good: All four lifecycle events handled, typed event parameters, named constant for URL

Full implementation: [examples/core.md](examples/core.md) Pattern 1

Pattern 2: Exponential Backoff with Jitter

Reconnection attempts must use exponential backoff with jitter to prevent all clients from reconnecting simultaneously (thundering herd problem). Cap delay at a maximum and limit total retry attempts.

const INITIAL_BACKOFF_MS = 1000;
const MAX_BACKOFF_MS = 30000;
const BACKOFF_MULTIPLIER = 2;
const JITTER_FACTOR = 0.5;

function calculateBackoff(attempt: number): number {
  const exponential = Math.min(
    INITIAL_BACKOFF_MS * Math.pow(BACKOFF_MULTIPLIER, attempt),
    MAX_BACKOFF_MS,
  );
  const jitter = exponential * JITTER_FACTOR * (Math.random() * 2 - 1);
  return Math.floor(exponential + jitter);
}

Why good: Jitter prevents thundering herd, capped maximum delay, retry limit prevents infinite loops

Full reconnecting class: [examples/core.md](examples/core.md) Pattern 2

Pattern 3: Heartbeat/Ping-Pong

Heartbeats detect dead connections and prevent intermediate infrastructure from closing idle connections. Send a ping on an interval; if pong is not received within a timeout, consider the connection dead.

const HEARTBEAT_INTERVAL_MS = 30000;
const HEARTBEAT_TIMEOUT_MS = 10000;

// Send ping -> start timeout -> if pong received, clear timeout
// If timeout fires without pong -> connection is dead, close and reconnect

When to use: All WebSocket connections, especially those that may be idle for extended periods or pass through NATs/proxies.

Full implementation: [examples/core.md](examples/core.md) Pattern 3

Pattern 4: Message Queuing During Disconnection

Messages sent during disconnection are lost. Queue them and flush when connection is restored. Limit queue size to prevent unbounded memory growth.

const MAX_QUEUE_SIZE = 100;

public send(data: unknown): void {
  if (this.socket?.readyState === WebSocket.OPEN) {
    this.socket.send(JSON.stringify(data));
  } else {
    this.queueMessage(data); // Queue with size limit
  }
}

Why good: Queue has size limit, oldest messages dropped when full, flush on reconnect, readyState check before sending

Full implementation: [examples/core.md](examples/core.md) Pattern 4

Pattern 5: Type-Safe Messages with Discriminated Unions

Use discriminated unions with a shared type field for compile-time type safety and exhaustive handling. Define separate types for client-to-server and server-to-client messages.

type ServerMessage =
  | { type: "subscribed"; channel: string; members: string[] }
  | { type: "message"; channel: string; content: string; sender: string }
  | { type: "error"; code: number; message: string };

function handleServerMessage(message: ServerMessage): void {
  switch (message.type) {
    case "subscribed":
      /* ... */ break;
    case "message":
      /* ... */ break;
    case "error":
      /* ... */ break;
    default:
      const exhaustiveCheck: never = message; // Compile error if case missing
  }
}

Why good: Discriminated union enables type narrowing, exhaustiveness check catche

Compartilhar X LinkedIn