msw: ESM build does not work in the browser ("debug")

Describe the bug

The es module build ships bare module imports, which can be resolved using a dev server or other tool. But when using the es module build in the browser it fails because it’s importing the “debug” module which is actually a commonjs module.

Environment

  • msw: 0.35.0
  • nodejs: 16.4.0
  • npm: 7.18.0

Please also provide your browser version.

To Reproduce

Steps to reproduce the behavior:

  1. Create a simple HTML page that imports MSW:
<!DOCTYPE html>
<html>
  <head></head>
  <body>
    <script type="module">
      import * as mswjs from 'msw';
      console.log(mswjs);
    </script>
  </body>
</html>
  1. Use a dev server that resolved bare imports, for example @web/dev-server: npx web-dev-server --node-resolve --open
  2. Visit the HTML page
  3. See this error: Uncaught SyntaxError: The requested module './../../../debug/src/index.js' does not provide an export named 'default'

Expected behavior

MSW imports a browser compatible module.

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 3
  • Comments: 18 (11 by maintainers)

Most upvoted comments

Since debug is only a small module, I recommend bundling it into the esm build of MSW. Or to create a separate output with all dependencies bundled.

In case anybody else wants to use msw as a pure ESM package, I’ve published a bundled ESM version under @bundled-es-mobules/msw, until the upstream package finds an ESM-friendly way forward 🙂

<html>
  <body>
    <script type="module">
      import {rest} from '@bundled-es-modules/msw';
      console.log(rest);
    </script>
  </body>
</html>

Currently running into this issue too. Running the following code:

<html>
  <body>
    <script type="module">
      import {rest} from 'msw';
      console.log(rest);
    </script>
  </body>
</html>

And run it with:

npx @web/dev-server --node-resolve --open

Results in:

Uncaught SyntaxError: The requested module './../../../@mswjs/interceptors/lib/utils/getCleanUrl.js' does not provide an export named 'getCleanUrl'

Because indeed getCleanUrl.js is commonjs:

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getCleanUrl = void 0;
/**
 * Removes query parameters and hashes from a given URL.
 */
function getCleanUrl(url, isAbsolute) {
    if (isAbsolute === void 0) { isAbsolute = true; }
    return [isAbsolute && url.origin, url.pathname].filter(Boolean).join('');
}
exports.getCleanUrl = getCleanUrl;
//# sourceMappingURL=getCleanUrl.js.map

It would be great to find a solution for this 🙂 I’d love to start using msw. Given some discussion/pointers, id probably be able to spend some time to contribute towards a solution for this issue. For example, would it be possible to ship both esm/cjs for the @mswjs/interceptors and @mswjs/cookies packages, and adding an exports map? e.g.: https://www.sensedeep.com/blog/posts/2021/how-to-create-single-source-npm-module.html

@patrickmcdougle-okta @kettanaito unfortunately that’s not the case. Even if debug is there in the node_modules, the module itself doesn’t work in the browser because it uses commonjs syntax not es module. So adding it as a dependency won’t solve it.

I think the problem is that debug is externalized in the esm build and therefore is not bundled into the rolled-up version of the library. Since we don’t declare it as a dependency, it’s not guaranteed to be in a consumers node_modules. Therefore, we need to have one or the other. Either 1.) Stop externalizing it in the esm build, OR 2.) Declare it as a dependency or peerDependency. (IMO dependency is more appropriate in this case)

See also #851