{"record":{"id":"ec529b1f7329accb","repo":"websockets/ws","slug":"ws-does-not-work-in-the-browser-browser-clients-m","errorCode":null,"errorMessage":"ws does not work in the browser. Browser clients must use the native WebSocket object","messagePattern":"ws does not work in the browser\\. Browser clients must use the native WebSocket object","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"browser.js","lineNumber":4,"sourceCode":"'use strict';\n\nmodule.exports = function () {\n  throw new Error(\n    'ws does not work in the browser. Browser clients must use the native ' +\n      'WebSocket object'\n  );\n};\n","sourceCodeStart":1,"sourceCodeEnd":9,"githubUrl":"https://github.com/websockets/ws/blob/c791e707eab3c13dd9a261d2479c3cc4a49a6fed/browser.js#L1-L9","documentation":"The `ws` package's package.json sets \"browser\": \"browser.js\", so any bundler that honors the browser field (webpack, vite, rollup via browser-field plugin, esbuild with platform=browser) resolves `require('ws')`/`import ... from 'ws'` to this 8-line stub, which throws synchronously on import. `ws` relies on Node core modules (net, tls, crypto, stream, zlib) that do not exist in a browser, and browsers already ship a native `WebSocket`, so the library refuses to load rather than silently break. The throw happens at module-evaluation time, so it surfaces as a top-level crash of the bundle.","triggerScenarios":"Building a web bundle that imports `ws` directly with target 'web' or platform 'browser'; an isomorphic/SSR app whose client entry pulls in `ws` instead of the native `WebSocket`; a dependency (e.g. a GraphQL/mqtt/stomp client) that internally `require('ws')` and gets bundled for the browser.","commonSituations":"Sharing the same networking module between a Node server and a browser client; migrating from Node to a browser target without swapping the WebSocket implementation; SSR frameworks (Next.js, Nuxt) that compile the same code for both runtimes; copy-pasted examples that `import WebSocket from 'ws'`.","solutions":["In browser code, use the global native `WebSocket` instead of importing `ws` (no import statement needed).","Use an isomorphic wrapper such as `isomorphic-ws` that returns native `WebSocket` in the browser and `ws` on Node.","Configure your bundler to alias `ws` to a browser polyfill (e.g. `websocket` package) or to `false`/an empty module in the browser build.","Split client and server entry points so `ws` is only imported from the Node entry, never from code the bundler emits for the browser."],"exampleFix":"// before\nimport WebSocket from 'ws';\nconst socket = new WebSocket('wss://example.com');\n\n// after (browser entry — no import, use the global)\nconst socket = new WebSocket('wss://example.com');","handlingStrategy":"fallback","validationCode":"// Detect a browser environment before importing ws.\nconst isBrowser =\n  typeof window !== 'undefined' && typeof window.document !== 'undefined';\nif (isBrowser) {\n  // Use the native WebSocket; never import `ws` here.\n}","typeGuard":"// isomorphic getter: native WebSocket in browsers, ws on Node\nfunction getWebSocketImpl() {\n  if (typeof window !== 'undefined' && typeof window.WebSocket !== 'undefined') {\n    return window.WebSocket;\n  }\n  // eslint-disable-next-line global-require\n  return require('ws');\n}","tryCatchPattern":null,"preventionTips":["Keep `ws` imports out of any module that a browser bundler can reach; gate them behind a Node-only entry point.","Configure webpack/vite/rollup to alias `ws` to a stub or to `false` in the browser build, or use `isomorphic-ws`.","Add a lint rule or a bundler resolve check that fails the build if `ws` leaks into a browser chunk."],"tags":["browser","bundler","webpack","isomorphic","environment"],"backgroundTag":null,"analyzedSha":"c791e707eab3c13dd9a261d2479c3cc4a49a6fed","analyzedAt":"2026-08-06T19:07:51.047Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}