Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ESM build does not work in the browser ("debug") #912

Closed
LarsDenBakker opened this issue Sep 13, 2021 · 18 comments · Fixed by #913
Closed

ESM build does not work in the browser ("debug") #912

LarsDenBakker opened this issue Sep 13, 2021 · 18 comments · Fixed by #913
Labels
bug Something isn't working help wanted Extra attention is needed needs:discussion

Comments

@LarsDenBakker
Copy link

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.

@LarsDenBakker LarsDenBakker added the bug Something isn't working label Sep 13, 2021
@LarsDenBakker LarsDenBakker changed the title Es module build is not a real es module Es module build does not work in the browser Sep 13, 2021
@kettanaito
Copy link
Member

Hey, @LarsDenBakker. Thanks for reporting this.

This issue may be related to #851, as MSW doesn't rely on the debug package directly, it's a dependency of another module called @mswjs/interceptors. We may be able to solve this by fixing the build process of interceptors and not bundling the debug module so that it's evaluated in the browser as intended. On the other hand, I have no guarantee that the debug module has an ES-compatible build target—that needs to be tested.

@LarsDenBakker
Copy link
Author

LarsDenBakker commented Sep 14, 2021

It's not really the same issue. The debug module can never run in the browser because it's using commonjs syntax, it needs to be transformed before being browser compatible. Even the intended code you're linking is not browser compatible. Tools like webpack or jest do this automagically for you, but that is not the case for many other tools or when using no tools at all.

One solution is for @mswjs/interceptors to not use the debug module, or use a browser compatible variant.

Another is to bundle debug into the esm build, rollup can make it browser compatible.

@kettanaito
Copy link
Member

Tools like webpack or jest do this automagically for you

That sounds great. I've never heard of compilers transforming non-ES modules into ES.

One solution is for @mswjs/interceptors to not use the debug module, or use a browser compatible variant.

Not to use debug is not an option. debug can also run in the browser perfectly fine, having a designated browser bundle. I believe what you're referring to as "compatibility" is that it's not written as an ESM, apparently.

@patrickmcdougle-okta
Copy link
Contributor

patrickmcdougle-okta commented Sep 15, 2021

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

@kettanaito
Copy link
Member

Let’s discuss the debug issue in the respected GitHub ticket. Thanks for the feedback, I think you’re right in saying we need to specify debug as a dependency.

@LarsDenBakker
Copy link
Author

LarsDenBakker commented Sep 16, 2021

@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.

@kettanaito
Copy link
Member

To clarify, when speaking "doesn't work in the browser" you're referring to using ES in a browser (via <script type="module">). debug itself has a browser build which, I think, is UMD, that functions fine in the browser.

@kettanaito kettanaito reopened this Sep 16, 2021
@LarsDenBakker
Copy link
Author

Yep trying to use it using the module loader of the browser.

@patrickmcdougle-okta
Copy link
Contributor

patrickmcdougle-okta commented Sep 16, 2021

When it's pulled in as a dependency instead of rolled up, I think the index file with the dynamic require will be preserved (vs treeshaken / collapsed) and this won't be an issue. Rollup is forcing the node version to be rolled up into it.

Edit: I think I'm wrong...however debug doesn't even bundle an esm version in the package (and probably never will), so thats probably not going to work.

@LarsDenBakker
Copy link
Author

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.

@kettanaito kettanaito changed the title Es module build does not work in the browser ESM build does not work in the browser ("debug") Dec 6, 2021
@kettanaito kettanaito added help wanted Extra attention is needed and removed potentially solved labels Dec 6, 2021
@thepassle
Copy link
Contributor

thepassle commented Mar 16, 2022

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

@thepassle
Copy link
Contributor

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>

@kettanaito
Copy link
Member

I'm improving the build modules in #1247, which may affect this in a good way. It's true that @mswjs/interceptors is not distributed as an ESM, so there may be issues simply because of that. I'm planning on adding a proper build pipeline to that dependency as well (hopefully, to all ecosystem dependencies) as soon as I have time.

@sashafirsov
Copy link

sashafirsov commented Mar 13, 2023

The work around is to substitute msw by import maps with re-export of IIFE distribution. Working example

CC @thepassle

@mfrieling
Copy link

I have the same issue with an NX monorepo with Angular. I followed this tutorial to setup msw. But I get warnings for a lot more packages than listed here:

@mswjs/cookies
@mswjs/interceptors
@mswjs/interceptors/lib/interceptors/XMLHttpRequest
@mswjs/interceptors/lib/interceptors/fetch
@mswjs/interceptors/lib/utils/bufferUtils.js
@mswjs/interceptors/lib/utils/getCleanUrl.js
@open-draft/until
cookie
headers-polyfill
is-node-process
js-levenshtein
node-fetch
outvariant
strict-event-emitter

The last warning is a bit strange:

WARNING undefined depends on 'msw'. CommonJS or AMD dependencies can cause optimization bailouts.

Versions

  • Node: 18.16.0
  • Yarn: 3.6.0
  • Angular CLI: 16.0.6
  • NX CLI: 16.3.2
  • MSW: 1.2.2
  • OS: Ubuntu 22 (WSL 2)

@kettanaito
Copy link
Member

I can confirm that MSW 2.0 works correctly in the browser. Please test this and let me know.

@mfrieling
Copy link

@kettanaito what about MSW 1.2? Since there are a lot of breaking changes for many developers/projects it might not be possible to upgrade soon.

@kettanaito
Copy link
Member

@mfrieling, I understand that. That's why I spent a lot of time writing the Migration guidelines, which also include common problems and how to address them at the bottom. I strongly encourage everybody to upgrade, as many people have already done.

There will be no new features and even bug fixes to 1.x. Exception being critical vulnerabilities but I highly doubt those will happen (1.x is the direct continuation of 0.x and we haven't got any critical issues in years).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working help wanted Extra attention is needed needs:discussion
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants