WuKongIM Docs

Web quickstart

Install exactly easyjssdk 2.0.4 and use a product BFF plus contiguous TypeScript code for an online browser messaging loop.

The browser asks the product BFF for the current user's connection material, then EasyJSSDK establishes a WebSocket JSON-RPC connection. The client holds no Product HTTP management credential, and Alice and Bob accept the path in two isolated browser contexts.

The current Product Gateway supports this connection path

The current Product Gateway supports pinned v2.0.4 JSON-RPC CONNECT and online bidirectional messaging, including requests without jsonrpc, Base64 SEND, and object RECV. Browsers default to WEB 1; the full wire set is APP 0, WEB 1, and PC 2. The tutorial installs npm 2.0.4. The official browser example passed at source revision a055b3667247333b6b3183249f5d5929673dfd53, which is now included in the v2.0.4 Release. The npm artifact then completed bidirectional messaging and disconnect in Chrome 151 and hosted released-package peer runs.

What you will have

  • An npm dependency pinned to easyjssdk@2.0.4.
  • A browser client that consumes only a minimal product-BFF response.
  • Event callbacks that can be removed precisely with off, plus page-exit cleanup.
  • Two independent observations: Alice's send result and Bob's realtime receive.

Check out the exact source to reproduce the verified path:

git clone https://github.com/WuKongIM/WuKongEasySDK-JS.git
cd WuKongEasySDK-JS
git checkout a055b3667247333b6b3183249f5d5929673dfd53
npm ci
npm test
npm run build
python3 -m http.server 8080

Open http://127.0.0.1:8080/example/. Run the Official Examples covers WuKongIM startup, Alice/Bob preparation, and endpoint mapping. The source example and npm 2.0.4 artifact now have separate runtime receipts; keep those evidence classes distinct.

Before you begin

Prepare the following:

  • A modern browser with native WebSocket, TextEncoder, and TextDecoder.
  • A WuKongIM single-node cluster or multi-node cluster whose /readyz is healthy and whose WebSocket Gateway is browser-reachable.
  • A same-origin product BFF, or one with a deliberately configured cross-origin policy.
  • A BFF that validates the product session and returns uid, a short-lived token, and websocketUrl for the current user.

Read Identity & Token first. Production pages and WebSockets use HTTPS/WSS, and tokens never belong in URLs, Local Storage, logs, or analytics events.

Step 1: install an exact version

Run this in an existing Vite, Next.js, or other bundled application:

npm install --save-exact easyjssdk@2.0.4

Commit package-lock.json. This tutorial does not use a floating CDN version that could silently replace the SDK after a page refresh.

Step 2: obtain connection material from the product BFF

/api/im/bootstrap below is your product route, not WuKongIM Product HTTP. The BFF validates the server-side login session, issues a short-lived token, and safely selects the WebSocket address returned by /route:

interface IMBootstrap {
  uid: string;
  token: string;
  websocketUrl: string;
}

async function fetchIMBootstrap(): Promise<IMBootstrap> {
  const response = await fetch('/api/im/bootstrap', {
    credentials: 'include',
    cache: 'no-store',
    headers: { accept: 'application/json' },
  });
  if (!response.ok) throw new Error(`IM bootstrap failed: ${response.status}`);
  return response.json() as Promise<IMBootstrap>;
}

The browser never calls /user/token or /route directly. Their management boundary, server credential, and response filtering remain inside the BFF.

Step 3: initialize, subscribe, and connect

on receives a function reference; off must receive the same reference. This example disables global-singleton mode so hot reload, tests, or a multi-instance page cannot silently destroy another client:

import { WKIM, WKIMChannelType, WKIMEvent } from 'easyjssdk';

export class EasyChatClient {
  private im?: WKIM;
  private readonly messages = new Map<string, unknown>();

  private readonly onConnect = (_result: unknown) => {
    console.info('EasySDK connected');
  };

  private readonly onDisconnect = (_info: unknown) => {
    console.info('EasySDK disconnected');
  };

  private readonly onMessage = (message: any) => {
    if (this.messages.has(message.messageId)) return;
    this.messages.set(message.messageId, message);
    // Pass the deduplicated message to application state.
  };

  private readonly onError = (_error: unknown) => {
    console.error('EasySDK operation failed');
  };

  async start(bootstrap: IMBootstrap): Promise<void> {
    this.stop();

    const im = WKIM.init(
      bootstrap.websocketUrl,
      { uid: bootstrap.uid, token: bootstrap.token },
      { singleton: false, debugLogging: false },
    );
    im.on(WKIMEvent.Connect, this.onConnect);
    im.on(WKIMEvent.Disconnect, this.onDisconnect);
    im.on(WKIMEvent.Message, this.onMessage);
    im.on(WKIMEvent.Error, this.onError);

    this.im = im;
    await this.connectWithin(im, 10_000);
  }

  private async connectWithin(im: WKIM, timeoutMs: number): Promise<void> {
    let timeout: ReturnType<typeof setTimeout> | undefined;
    try {
      await Promise.race([
        im.connect(),
        new Promise<void>((_, reject) => {
          timeout = setTimeout(
            () => reject(new Error(`EasySDK connect exceeded ${timeoutMs} ms`)),
            timeoutMs,
          );
        }),
      ]);
    } catch (error) {
      im.destroy();
      if (this.im === im) this.im = undefined;
      throw error;
    } finally {
      if (timeout) clearTimeout(timeout);
    }
  }

  async sendText(targetUid: string, text: string) {
    if (!this.im?.isConnected) throw new Error('EasySDK is not connected');

    return this.im.send(targetUid, WKIMChannelType.Person, {
      type: 1,
      version: 1,
      content: text,
    });
  }

  stop(): void {
    const im = this.im;
    if (!im) return;

    im.off(WKIMEvent.Connect, this.onConnect);
    im.off(WKIMEvent.Disconnect, this.onDisconnect);
    im.off(WKIMEvent.Message, this.onMessage);
    im.off(WKIMEvent.Error, this.onError);
    im.destroy();
    this.im = undefined;
  }
}

debugLogging: false matches the SDK default and is written explicitly here so production configuration can be reviewed. Set it to true only during a controlled diagnostic window; the SDK still emits only sanitized operational metadata, and application callbacks or collectors must not log complete events, results, or payloads.

An application normally creates one EasyChatClient. The SDK has an internal timeout for the CONNECT JSON-RPC request, but the WebSocket-open phase can still hang; connectWithin bounds the complete wait at 10 seconds and calls destroy after failure. React can keep the client in a root-level Provider and call stop() from an Effect cleanup. Vue and Svelte use the corresponding component or application unmount hook.

Step 4: send the first message

const chat = new EasyChatClient();
const alice = await fetchIMBootstrap();

await chat.start(alice);
await chat.sendText('bob', 'Hello from Web EasySDK');
console.info('SEND completed');

window.addEventListener('pagehide', () => chat.stop(), { once: true });

Alice's resolved Promise means the send request received a server result. Bob must still observe the message in an independent page through WKIMEvent.Message. Do not render Alice's send result as proof that Bob read or processed it.

Step 5: accept with Alice and Bob

  1. Open two independent browser profiles or isolated browser contexts and sign in as Alice and Bob.
  2. Both sides obtain connection material from their own product session and observe WKIMEvent.Connect.
  3. Have Alice send to the person Channel bob, retaining the send result.
  4. On Bob, verify fromUid, channelId, messageId, and payload.
  5. Have Bob send back to Alice and prove the reverse direction.
  6. Use an unreachable address and confirm failure plus destroy within 10 seconds, rather than leaving the page in Connecting forever.
  7. Refresh, close, or sign out and confirm that the old instance called off and destroy, leaving no duplicate connection.

That exact source ran against the same WuKongIM revision in Chrome 151 and completed bidirectional messaging, manual disconnect, and reconnect. The npm 2.0.4 artifact also completed bidirectional messaging, SENDACK, and disconnect in real Chrome and hosted released-package peer runs. The loop still does not cover offline synchronization or production WSS. When Bob is offline, the application cannot wait only for an EasySDK realtime event; it needs a product-designed durable synchronization path.

Troubleshooting

  • The page says WebSocket or encoding APIs are missing: confirm the browser and build environment provide WebSocket, TextEncoder, and TextDecoder; do not infer Mini Program support from the browser path.
  • Connection is rejected before ready: inspect the BFF-returned WSS address, token lifetime, certificate, proxy Upgrade, and Gateway reachability.
  • Messages duplicate after refresh: do not call on during every component render; retain callbacks and call off/destroy during unmount.
  • The console still contains a token or payload: first use the lockfile and browser bundle to confirm that easyjssdk@2.0.4 is actually shipped, then inspect application event callbacks, error handling, and collectors for complete-object logging. SDK diagnostics are off by default and should emit only sanitized operational metadata when explicitly enabled. Reproduce with the npm artifact and retain only low-sensitivity evidence before filing an issue.
  • You need an executable Web scenario path: use the WuKongIMJSSDK Web tutorial, which has the site's protected verification flow, and review the current build and runtime boundaries under API Versions & Compatibility. Do not mix method names between the two SDKs.

Before production

  • Serve both the page and WebSocket over HTTPS/WSS, then verify certificates, proxy Upgrade, the BFF origin policy, and Gateway reachability.
  • Return only the current session's connection material from the BFF; tokens never belong in URLs, Local Storage, logs, or analytics events.
  • debugLogging is off by default. Keep it false in production and inspect the actual npm 2.0.4 bundle, Console, error reporting, and collectors with non-production canaries for tokens, payloads, raw frames, or complete event objects.
  • Retain the lockfile, browser and build versions, network, and server revision; separately verify refresh, logout, reconnect, and durable recovery while Bob is offline.
  • Continue with Integration Acceptance for capacity, observability, upgrades, and rollback.

Next

Return to the WuKongEasySDK overview, or continue with Messaging, Offline Messages & Push, and the Release Checks.

On this page