mswjs / msw

Industry standard API mocking for JavaScript.
https://mswjs.io
MIT License
15.97k stars 519 forks source link

TypeError: Cannot set property WebSocket of #<Object> which has only a getter (Next.js) #2339

Closed lasseklovstad closed 3 weeks ago

lasseklovstad commented 3 weeks ago

Prerequisites

Environment check

Node.js version

20

Reproduction repository

https://github.com/lasseklovstad/msw-websocker-bug-nextjs

Reproduction steps

Run npm i, npm run dev and open the nextjs app

Current behavior

node_modules\@mswjs\interceptors\lib\browser\interceptors\WebSocket\index.mjs (668:1) @ _WebSocketInterceptor.setup ⨯ TypeError: Cannot set property WebSocket of #<Object> which has only a getter

Expected behavior

Nextjs app should work as before.

kettanaito commented 3 weeks ago

Hi, @lasseklovstad. Thanks for reporting this!

I will take a look at this once I have a moment, I think I know the root cause of this.

kettanaito commented 3 weeks ago

Root cause

The issue is caused by Next.js defining the global WebSocket class (as it's missing in Node.js v20) in a way that forbids overrides:

https://github.com/vercel/next.js/blob/de4f197e2fde19526ee019fbebb068e962b58fc0/packages/next/src/server/node-environment-baseline.ts#L11-L15

This property definition doesn't support setters and doesn't have configurable: true to re-define this property. This is an extremely restrictive way to re-define a global.

Solution

Ideally, open a PR to Next to define that property with configurable: true. They don't own the WebSocket class, but even if they did, defining a global this way is too restrictive. This is a similar issue to how they used to define fetch in a way that was not overridable.

kettanaito commented 3 weeks ago

I've opened a pull request to Next.js to fix this issue: https://github.com/vercel/next.js/pull/72079. Hope the team will have time to look into this. Meanwhile, closed. Not an MSW issue. Please follow the progress at the linked pull request.

kettanaito commented 3 weeks ago

I still think MSW should have a better developer experience around non-configurable globals, so I'm adding an error and disabling the interceptor if that's the case: https://github.com/mswjs/interceptors/pull/665. Will make it easier to debug for everyone.