mswjs / msw

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

Bug: Module not found: Can't resolve '_http_common' in Next.js #2291

Closed ck-euan closed 2 months ago

ck-euan commented 2 months ago

Prerequisites

Environment check

Node.js version

v20.17.0

Reproduction repository

https://github.com/ck-euan/msw-bug-example

Reproduction steps

  1. Run the dev script to start the Next.js app and you should see the error in the console.
  2. Downgrade to msw 2.4.3 or below and run the dev script and the issue isn't there

Current behavior

After upgrading to 2.4.4 and above, I encounter the following error when running my Next.js app:

 ⨯ ./node_modules/.pnpm/@mswjs+interceptors@0.35.6/node_modules/@mswjs/interceptors/lib/node/chunk-RWGRRMVU.mjs:21:1
Module not found: Can't resolve '_http_common'

https://nextjs.org/docs/messages/module-not-found

Import trace for requested module:
./node_modules/.pnpm/@mswjs+interceptors@0.35.6/node_modules/@mswjs/interceptors/lib/node/interceptors/ClientRequest/index.mjs
./node_modules/.pnpm/msw@2.4.7_typescript@5.5.4/node_modules/msw/lib/node/index.mjs
./tests/mocks/node.ts
./src/instrumentation.ts
Error: An error occurred while loading instrumentation hook: Cannot find module '/Users/euanmorgan/dev/msw-bug/.next/server/instrumentation'
Require stack:
- /Users/euanmorgan/dev/msw-bug/node_modules/.pnpm/next@14.2.8_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/dev/next-dev-server.js
- /Users/euanmorgan/dev/msw-bug/node_modules/.pnpm/next@14.2.8_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next.js
- /Users/euanmorgan/dev/msw-bug/node_modules/.pnpm/next@14.2.8_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/start-server.js
    at Module._resolveFilename (node:internal/modules/cjs/loader:1225:15)
    at /Users/euanmorgan/dev/msw-bug/node_modules/.pnpm/next@14.2.8_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/require-hook.js:55:36
    at Module._load (node:internal/modules/cjs/loader:1051:27)
    at Module.require (node:internal/modules/cjs/loader:1311:19)
    at mod.require (/Users/euanmorgan/dev/msw-bug/node_modules/.pnpm/next@14.2.8_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/require-hook.js:65:28)
    at require (node:internal/modules/helpers:179:18)
    at DevServer.runInstrumentationHookIfAvailable (/Users/euanmorgan/dev/msw-bug/node_modules/.pnpm/next@14.2.8_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/dev/next-dev-server.js:436:51)
    at async Span.traceAsyncFn (/Users/euanmorgan/dev/msw-bug/node_modules/.pnpm/next@14.2.8_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/trace/trace.js:154:20)
    at async DevServer.prepareImpl (/Users/euanmorgan/dev/msw-bug/node_modules/.pnpm/next@14.2.8_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/dev/next-dev-server.js:214:9)
    at async NextServer.prepare (/Users/euanmorgan/dev/msw-bug/node_modules/.pnpm/next@14.2.8_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next.js:161:13)
    at async initializeImpl (/Users/euanmorgan/dev/msw-bug/node_modules/.pnpm/next@14.2.8_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/render-server.js:98:5)
    at async initialize (/Users/euanmorgan/dev/msw-bug/node_modules/.pnpm/next@14.2.8_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/router-server.js:420:22)
    at async Server.<anonymous> (/Users/euanmorgan/dev/msw-bug/node_modules/.pnpm/next@14.2.8_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/start-server.js:249:36) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    '/Users/euanmorgan/dev/msw-bug/node_modules/.pnpm/next@14.2.8_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/dev/next-dev-server.js',
    '/Users/euanmorgan/dev/msw-bug/node_modules/.pnpm/next@14.2.8_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/next.js',
    '/Users/euanmorgan/dev/msw-bug/node_modules/.pnpm/next@14.2.8_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/next/dist/server/lib/start-server.js'
  ]
}

Expected behavior

The app should run without errors with the msw server running via the Next.js instrumentation hook

AlanSl commented 2 months ago

Can confirm, same issue (I tested on node 18, pnpm 9, any NextJS 14.2 patch release including latest).

MSW <= 2.4.3 works but any MSW version >= 2.4.4 fails during nextjs build with:

./node_modules/.pnpm/@mswjs+interceptors@0.35.6/node_modules/@mswjs/interceptors/lib/node/chunk-RWGRRMVU.mjs
Module not found: Can't resolve '_http_common'
Seungwoo321 commented 2 months ago

next.config.mjs

/** @type {import('next').NextConfig} */
const nextConfig = {
  webpack: (config, { isServer }) => {
    if (isServer) {
      config.externals = [...(config.externals || []), '_http_common'];
      config.target = 'node';
    }

    return config;
  }
};

export default nextConfig;

This worked with next@14.2.11 and msw@2.4.8.

kettanaito commented 2 months ago

Thanks for reporting this, @ck-euan.

_http_common is a built-in module in Node.js. I wonder why Next.js has problem importing it.

node

require('_http_common')
// ...see exports.

This is likely a bug on Next.js side (the _http_common is sort of internal, but it exists, and mustn't throw when importing it).

There's an exact issue about it from long ago (https://github.com/vercel/next.js/issues/30091) but it doesn't have any resolution.

kettanaito commented 2 months ago

Opened an issue with Next.js: https://github.com/vercel/next.js/issues/70262. Until proven otherwise, this has nothing to do with MSW. Please track the progress in that issue. Thanks.

Sly777 commented 2 months ago

next.config.mjs

/** @type {import('next').NextConfig} */
const nextConfig = {
  webpack: (config, { isServer }) => {
    if (isServer) {
      config.externals = [...(config.externals || []), '_http_common'];
      config.target = 'node';
    }

    return config;
  }
};

export default nextConfig;

This worked with next@14.2.11 and msw@2.4.8.

  • node v22.7.0
  • pnpm v9.9.0

This workaround works at the moment. (node.js v22.6.0, "next": "14.2.13", "msw": "^2.4.9")

aifirstd3v commented 1 month ago

The following is written by my GPT4o :)

Error Analysis

As the error message suggests, the issue arises because the module "_http_common" could not be found. This error is related to MSW (Mock Service Worker) using the @mswjs/interceptors library in Node.js environments to intercept network requests, where the internal _http_common module is used. However, Next.js's default webpack configuration does not handle this module, resulting in this error.

Explanation of the webpack Configuration

/** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    instrumentationHook: true
  },
  webpack: (config, { isServer }) => {
    // Apply configuration only in the server environment
    if (isServer) {
      // Add '_http_common' to config.externals to treat it as an external module
      config.externals = [...(config.externals || []), '_http_common'];

      // Set webpack target to 'node' to support building for Node.js environments
      config.target = 'node';
    }

    return config;
  }
}

export default nextConfig;

Explanation of the webpack Code:

  1. if (isServer):

    • This condition ensures that the configuration is only applied in the server environment. Since Next.js operates in both the browser and server environments, this setting solves issues that arise only on the server side.
  2. config.externals = [...(config.externals || []), '_http_common']:

    • This part adds the "_http_common" module to externals, meaning webpack will treat it as an external module and not include it in the bundle.
    • Modules added to externals are not bundled but are instead handled by Node.js at runtime.
  3. config.target = 'node':

    • Setting webpack's target to 'node' ensures that the bundle is optimized for execution in Node.js environments.
    • This is applied only in the server environment, allowing the Next.js server to handle Node.js modules.

Summary of the Solution

This configuration resolves the issue with Node.js built-in module errors related to MSW, allowing you to use MSW handlers without errors on the Next.js server.

kettanaito commented 1 month ago

I will make this abundantly clear for everyone:

This has been addressed in Next.js. Please wait or the next version and update to it, the fix is there. You can also use canary if you don't want to wait.