msw: Error `Class extends value undefined is not a constructor or null` occurs after the version upgrade from 0.49.2 to the latest version
Prerequisites
- I confirm my issue is not in the opened issues
- I confirm the Frequently Asked Questions didn’t contain the answer to my issue
Environment check
- I’m using the latest
msw
version - I’m using Node.js version 14 or higher
Browsers
Chromium (Chrome, Brave, etc.)
Reproduction repository
private code i am not allowed to share
Reproduction steps
I run into the error during the runtime after the MSW.js version upgrade. It happens to the version between v0.49.3 to v1.0.1.
All the version 0.49.3 works fine before v0.49.3 for me.
AsyncEventEmitter.js:11 Uncaught TypeError: Class extends value undefined is not a constructor or null
at __webpack_modules__../node_modules/@mswjs/interceptors/lib/utils/AsyncEventEmitter.js.__extends (AsyncEventEmitter.js:11:1)
at AsyncEventEmitter.js:85:1
at ./node_modules/@mswjs/interceptors/lib/utils/AsyncEventEmitter.js (AsyncEventEmitter.js:248:2)
at __webpack_require__ (bootstrap:24:1)
at fn (hot module replacement:62:1)
at ./node_modules/@mswjs/interceptors/lib/Interceptor.js (Interceptor.js:16:27)
at __webpack_require__ (bootstrap:24:1)
at fn (hot module replacement:62:1)
at ./node_modules/@mswjs/interceptors/lib/index.js (index.js:15:14)
at __webpack_require__ (bootstrap:24:1)
Current behavior
package.json contains: “msw”: “1.0.1”,
The entry point of the development mode. index.dev.tsx
.
...
const worker = require('@mock-api/browser').default
worker.start().then(() => {
renderApp()
})
The file handles the worker.
import { setupWorker } from 'msw'
import handlers from './handlers'
// This configures a Service Worker with the given request handlers.
const worker = setupWorker(...handlers())
export default worker
The file handles the handlers
...
import {
rest,
RestRequest,
PathParams,
ResponseResolver,
ResponseComposition,
RestContext,
} from 'msw'
export const handler = (responder = rest) => [
responder.get(
'....',
withAuth((req, res, ctx) =>
res(
ctx.status(200),
ctx.json({ ... })
)
)
),
...
Expected behavior
Working properly.
About this issue
- Original URL
- State: closed
- Created a year ago
- Reactions: 12
- Comments: 16 (3 by maintainers)
Thanks for the insights, everyone. The root cause seems to be for the
@mswjs/interceptors
code ending up in your bundle when usingmsw
import. May be a matter of a broken import somewhere in the source. Need investigation.How to solve this
I’ve opened a work-in-progress fix at https://github.com/mswjs/interceptors/pull/382. It requires quite a lot of changes to adopt the old version of Interceptors (0.17.9) to the newer
strict-event-emitter
. To add insult to injury, I’ve already spent a lot of time migrating to those changes as a part of #1404.I’m sorry to everyone blocked by this but I don’t have the capacity to dive into a week of refactoring to support a backport version. MSW 1.x is stale as I wrote countless times on Twitter, and I highly encourage you to update to
msw@next
. I’m certain it has this issue fixed there, just as dozens of other issues. Please read #1464 to make your migration easier (there’s a migration guideline inside).I wish I had more time to handle these projects with proper care, providing backport fixes and such. I simply don’t. I know it will make people sad but that’s the reality. You can change it, instead of being sad, by Sponsoring MSW.
If you are blocked by this, this is the best time to migrate to
msw@next
. Or you can pick up https://github.com/mswjs/interceptors/pull/382, look at what I did regardingEmitter
in #1404 and push those changes to the backport. Thanks for understanding.@JimLin94 I ran into this as well.
Going through the call stack, it looks like AsyncEventEmitter.js is an iife, and it’s called with
(strict_event_emitter_1.StrictEventEmitter))
. However, with the latest dependency upgrades, strict-event-emitter@0.4.6 no longer has a module calledStrictEventEmitter
.npm ls strict-event-emitter
gives this:Installing the older version -
npm install strict-event-emitter@0.2.8
- get me past that error, but then I run into this error fromSetupApi.ts
due to the old version ofstrict-event-emitter
not having the moduleEmitter
any longer.I experienced this when transitively importing
msw/node
in a bundle that was loaded on the client. I resolved this by removing themsw/node
import from the client bundle. I ended up withmocks.client.ts
andmocks.server.ts
, where onlymocks.server.ts
importedmsw/node
.I’m writing this now mostly for learning purposes since I found the problem really interesting and want to understand more how dependency resolution in this case works - I hope that is ok!
To sum up first: As others already pointed out, the problem is that
@mswjs/interceptors
has it’s own dependency onstrict-event-emitter@0.2.8
whilemsw
depends onstrict-event-emitter@0.4.6
. There is a breaking change between version 0.2.8 and 0.4.6 (which I understand according to Semantic Versioning is ok).What puzzles me is that when I create a fresh project with CRA and install the latest version of
msw
my yarn.lock file and mynode_modules
looks exactly the same as in a project which crashes withClass extends value undefined is not a constructor or null
.The
node_modules
folder in the root of the project in both cases looks like this:So in both cases it looks fine to me!
In the non-working app it seems now that node, when resolving the dependency in
@mswjs/interceptors
prioritizes the higher version ofstrict-event-emitter
from the root node_modules folder, despite having the correct version ofstrict-event-emitter
in the local node_modules folder.I would expect that node searches for
strict-event-emitter
in allnode_modules
up the directory chain. But this is not the case. When I printmodule.paths
, I can see that it only contains onenode_modules
(the root one):As compared to in the working, fresh CRA app:
Consequently, when I change the line where
strict-event-emitter
is imported inside@mswjs/interceptors
fromto the relative path
it is importing the correct version and works as expected.
Does anybody understand why node (or any other involved tooling) is changing module.paths from one app to another? Or point me to any learning material that could help to further understand the problem?
Just did a fresh install of msw and encountered this. The latest versions are broken this way out of the box, at least for some systems.
I can confirm, same issue as @dustinmyers msw@1.1.0
HI, any updates regarding this? thank you!
Same happens here. Upgrade from 0.49.2 to 1.2.1 and the error appears. Do not know what to do. Using node version 18.15.0. Using Yarn v3.5.0 in pnp. I was forced to add strict-event-emmiter to resolutions (v0.2.8 or v0.4.6) With 0.2.8 -> TypeError: import_strict_event_emitter.Emitter is not a constructor error appears. With 0.4.6 -> TypeError: Class extends value undefined is not a constructor or null error appears
A bit of a mess.
I will rollback to 0.49.2 and wait 😃
same issue in msw@1.1.1, downgrading to 49.2 fixes the problem but msw cant be updated to typescript 5.0
I came across this same issue in Remix. I fixed it by doing this:
The
typeof
check is important. Otherwise, it’ll try to run this in the browser and even thoughprocess
is not available in the browser, it will still be truthy and attempt to execute.