Skip to content

Fix 'WebSocket is not defined' #2158

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 29 additions & 14 deletions frontend/util/wsutil.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,42 @@
// Copyright 2025, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0

import type { WebSocket as NodeWebSocketType } from "ws";
// In browser builds `window` is defined and the global `WebSocket` constructor is
// available. When running inside the Electron *main* process (Node context),
// `window` is undefined and we must fall back to the `ws` npm package.

let NodeWebSocket: typeof NodeWebSocketType = null;
// Import only the *type* from `ws`; the actual module will be required lazily
// to avoid bundling issues when this file is transpiled for the renderer.
import type { WebSocket as NodeWebSocketType } from "ws";

if (typeof window === "undefined") {
// Necessary to avoid issues with Rollup: https://github.com/websockets/ws/issues/2057
import("ws")
.then((ws) => (NodeWebSocket = ws.default))
.catch((e) => {
console.log("Error importing 'ws':", e);
});
}
// Lazily initialised reference to the Node-side WebSocket constructor.
let NodeWebSocket: typeof NodeWebSocketType | null = null;

type ComboWebSocket = NodeWebSocketType | WebSocket;

function newWebSocket(url: string, headers: { [key: string]: string }): ComboWebSocket {
if (NodeWebSocket) {
function newWebSocket(
url: string,
headers?: { [key: string]: string } | null
): ComboWebSocket {
// Node / Electron main process path ─ use `ws` package.
if (typeof window === "undefined") {
if (!NodeWebSocket) {
// `require` ensures the module is loaded synchronously to avoid the
// timing issue that caused "WebSocket is not defined" errors when
// the previous asynchronous dynamic import had not completed yet.
// eslint-disable-next-line @typescript-eslint/no-var-requires
// @ts-ignore – CommonJS require is available in Node context.
const wsMod = require("ws") as typeof NodeWebSocketType | {
default: typeof NodeWebSocketType;
};
NodeWebSocket = (wsMod as any).default ?? (wsMod as any);
}
// At this point NodeWebSocket is guaranteed to be initialised.
return new NodeWebSocket(url, { headers });
} else {
return new WebSocket(url);
}

// Browser / renderer path ─ use the global WebSocket.
return new WebSocket(url);
}

export { newWebSocket };
Expand Down