Skip to content

feat!: migrate to esm-only - #2765

Merged
kettanaito merged 5 commits into
feat/3.0from
feat/esm-only
Jul 18, 2026
Merged

kettanaito merged 5 commits into
feat/3.0from
feat/esm-only

Conversation

@kettanaito

@kettanaito kettanaito commented Jul 18, 2026 •

Copy link
Copy Markdown
Member

Migrates MSW to be ESM-only 🎉 Finally.

@coderabbitai

coderabbitai Bot commented Jul 18, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 8fc308e5-29a1-4bd5-a384-9b2926d402b3

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/esm-only

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@socket-security

socket-security Bot commented Jul 18, 2026 •

Copy link
Copy Markdown

@kettanaito kettanaito mentioned this pull request Jul 18, 2026
37 tasks done
@pkg-pr-new

pkg-pr-new Bot commented Jul 18, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/msw@2765

commit: dabe4b3

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@config/plugins/rolldown/forceFileExtensionsPlugin.ts`:
- Around line 21-35: Update ESM_RELATIVE_IMPORT_EXP and modifyRelativeImports to
rewrite both from-clause and side-effect relative imports, while preserving
existing non-JavaScript extensions such as .json instead of appending
ESM_EXTENSION. Retain directory handling with /index and support
import-attribute syntax, then add coverage for side-effect, JSON, directory, and
import-attribute cases before publishing chunks.

In `@config/plugins/rolldown/resolveCoreImportsPlugin.ts`:
- Around line 3-31: Update resolveCoreImportsPlugin and replaceCoreImports so
the rewritten `#core` import path is calculated relative to each emitted chunk’s
fileName rather than hardcoding ../core. Pass the chunk fileName into the
replacement logic and preserve the existing submodule and semicolon handling
while resolving the correct relative path for nested output chunks.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: d0ec95d8-e1f9-4809-993c-7be555318409

📥 Commits

Reviewing files that changed from the base of the PR and between 5283bf7 and dabe4b3.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (20)
  • .oxlintrc.json
  • browser/package.json
  • cli/package.json
  • commitlint.config.js
  • config/package.json
  • config/plugins/rolldown/copyWorkerPlugin.ts
  • config/plugins/rolldown/forceFileExtensionsPlugin.ts
  • config/plugins/rolldown/resolveCoreImportsPlugin.ts
  • config/replaceCoreImports.js
  • config/scripts/patch-ts.js
  • config/scripts/postinstall.js
  • graphql/package.json
  • native/package.json
  • node/package.json
  • package.json
  • src/package.json
  • test/modules/node/esm-node.test.ts
  • test/support/alias.ts
  • test/support/msw-esm/package.json
  • tsdown.config.mts
💤 Files with no reviewable changes (10)
  • config/replaceCoreImports.js
  • node/package.json
  • cli/package.json
  • src/package.json
  • config/scripts/patch-ts.js
  • browser/package.json
  • graphql/package.json
  • config/package.json
  • native/package.json
  • test/support/msw-esm/package.json

Comment thread config/plugins/rolldown/forceFileExtensionsPlugin.ts
Comment thread config/plugins/rolldown/resolveCoreImportsPlugin.ts
@kettanaito
kettanaito merged commit be2ae7c into feat/3.0 Jul 18, 2026
21 checks passed
@kettanaito
kettanaito deleted the feat/esm-only branch July 18, 2026 16:30
renovate Bot added a commit to cigaleapp/cigale that referenced this pull request Oct 13, 2026
##### [v3.0.2](https://github.com/mswjs/msw/releases/tag/v3.0.2)

#### v3.0.2 (2026-10-03)

##### Bug Fixes

- **vite:** support `virtual:msw` imports in vitest ([#2802](mswjs/msw#2802)) ([`e73c381`](mswjs/msw@e73c381)) [@kettanaito](https://github.com/kettanaito)
##### [v3.0.1](https://github.com/mswjs/msw/releases/tag/v3.0.1)

#### v3.0.1 (2026-09-30)

##### Bug Fixes

- treat `CONNECT` requests as the transport mechanism ([#2796](mswjs/msw#2796)) ([`7cad86a`](mswjs/msw@7cad86a)) [@kettanaito](https://github.com/kettanaito)
##### [v3.0.0](https://github.com/mswjs/msw/releases/tag/v3.0.0)

#### v3.0.0 (2026-09-28)

- v3.0.0 ([#2692](mswjs/msw#2692)) ([`2bb4342`](mswjs/msw@2bb4342)) [@kettanaito](https://github.com/kettanaito) [@Andarist](https://github.com/Andarist)

##### ⚠️ BREAKING CHANGES

- **MSW is now ESM-only** ([#2765](mswjs/msw#2765)).
- Deprecate support for Node.js v18 and v20 ([#2729](mswjs/msw#2729)). The minimal supported Node.js version is v22.
- `msw/native` is removed in favor of [`@msw/react-native`](https://github.com/mswjs/react-native).
- Require TypeScript 5.9 as the minimal version.
- Deprecate support for TypeScript 5.1 and 5.2 ([#2730](mswjs/msw#2730))
- `worker.stop()` returns a Promise ([#2724](mswjs/msw#2724)). Awaiting it is relevant only for in-flight critical scenarios.
- `graphql` is now exported as `msw/graphql` ([#2691](mswjs/msw#2691)). GraphQL is now handled as a proper optional peer dependency.
- Removes the `handleRequest()` utility. Please use the `defineNetwork()` API instead.
- `GraphQLLinkHandlers` type has been renamed to `GraphQLLink`.
- The `file://` requests now throw in Node.js as they normally do (not supported by `fetch`).
- The `Content-Length` request header is now removed by `bypass()`.
- HTTP-to-WebSocket upgrade requests performed via `fetch()` now throw in Node.js as they normally do (not supported by `fetch`).
- Cookies are no longer managed in Node.js for better compatibilty. Instead, whatever is the default behavior of your environment that's the cookie behavior you get. This has no effect on the browser.
- WebSocket `connection` life cycle event has been renamed to `websocket:connection` ([#2783](mswjs/msw#2783)).
- `onUnhandledRequest` option has been renamed to `onUnhandledFrame`.
- The library no longer patches `setTimeout` to circumvent fake timers in test runners. You should advance the fake timers normally for delayed mocked responses to resolve.
- The library no longer returns a mocked cookie string on `request.headers.get('cookie')` in the handlers. It returns `null` in all environments. Please use the `cookies` resolver argument to have cookie-based logic.

##### Features

- Supports Node.js v24 and v26.
- Supports TypeScript v6.0 and v7.0.
- You can import individual utilities, like `delay` or `passthrough`, from the new `msw/utils` entrypoint for smaller footprint on your bundle.
- Support GraphQL v17.0.
- Support intercepting page navigations and form submissions ([#2721](mswjs/msw#2721)).
- Support GraphQL subscriptions ([#285](mswjs/msw#285), [#2763](mswjs/msw#2763)).
- Migrate from `path-to-regexp` to `@msw/url` ([#2678](mswjs/msw#2678)).
- Remove the following dependencies:
  - `graphql`
  - `path-to-regexp`
  - `picocolors`
  - `statuses`
  - `strict-event-emitter`
- Adds a Vite plugin for MSW ([#2781](mswjs/msw#2781)).
- Adds a `websocket:error` life cycle event to listen to WebSocket connection errors ([#2784](mswjs/msw#2784)).
- Support modifying the intercepted request headers in passthrough scenarios ([#2786](mswjs/msw#2786)).
- Support a new WebSocket Extension API that allows for better custom experiences ([#2791](mswjs/msw#2791)).

##### Bug fixes

- Fix an issue where preventing a page closure via the `beforeunload` listener would unregister the MSW worker ([#1105](mswjs/msw#1105)).
- Fix an issue that caused intermittent test failures in Vitest Browser Mode and Firefox if using `maxWorkers: 1` ([#2726](mswjs/msw#2726)).
- Fix an issue where in-flight requests were incorrectly passthrough when performed before calling `worker.stop()` ([#2724](mswjs/msw#2724), [#2597](mswjs/msw#2597)).
- Fix an issue where persisting cookies in `localStorage` would cause a maximum quota exceeded errors.
- Fix various issues related to the network interception in Node.js.
renovate Bot added a commit to cigaleapp/cigale that referenced this pull request Oct 17, 2026
##### [v3.0.3](https://github.com/mswjs/msw/releases/tag/v3.0.3)

#### v3.0.3 (2026-10-10)

##### Bug Fixes

- **HandlersController:** dispose of reset handlers ([#2810](mswjs/msw#2810)) ([`3818a81`](mswjs/msw@3818a81)) [@kettanaito](https://github.com/kettanaito)
- expose network context on `enable` in network sources ([#2809](mswjs/msw#2809)) ([`d1fe8e6`](mswjs/msw@d1fe8e6)) [@kettanaito](https://github.com/kettanaito)
##### [v3.0.2](https://github.com/mswjs/msw/releases/tag/v3.0.2)

#### v3.0.2 (2026-10-03)

##### Bug Fixes

- **vite:** support `virtual:msw` imports in vitest ([#2802](mswjs/msw#2802)) ([`e73c381`](mswjs/msw@e73c381)) [@kettanaito](https://github.com/kettanaito)
##### [v3.0.1](https://github.com/mswjs/msw/releases/tag/v3.0.1)

#### v3.0.1 (2026-09-30)

##### Bug Fixes

- treat `CONNECT` requests as the transport mechanism ([#2796](mswjs/msw#2796)) ([`7cad86a`](mswjs/msw@7cad86a)) [@kettanaito](https://github.com/kettanaito)
##### [v3.0.0](https://github.com/mswjs/msw/releases/tag/v3.0.0)

#### v3.0.0 (2026-09-28)

- v3.0.0 ([#2692](mswjs/msw#2692)) ([`2bb4342`](mswjs/msw@2bb4342)) [@kettanaito](https://github.com/kettanaito) [@Andarist](https://github.com/Andarist)

##### ⚠️ BREAKING CHANGES

- **MSW is now ESM-only** ([#2765](mswjs/msw#2765)).
- Deprecate support for Node.js v18 and v20 ([#2729](mswjs/msw#2729)). The minimal supported Node.js version is v22.
- `msw/native` is removed in favor of [`@msw/react-native`](https://github.com/mswjs/react-native).
- Require TypeScript 5.9 as the minimal version.
- Deprecate support for TypeScript 5.1 and 5.2 ([#2730](mswjs/msw#2730))
- `worker.stop()` returns a Promise ([#2724](mswjs/msw#2724)). Awaiting it is relevant only for in-flight critical scenarios.
- `graphql` is now exported as `msw/graphql` ([#2691](mswjs/msw#2691)). GraphQL is now handled as a proper optional peer dependency.
- Removes the `handleRequest()` utility. Please use the `defineNetwork()` API instead.
- `GraphQLLinkHandlers` type has been renamed to `GraphQLLink`.
- The `file://` requests now throw in Node.js as they normally do (not supported by `fetch`).
- The `Content-Length` request header is now removed by `bypass()`.
- HTTP-to-WebSocket upgrade requests performed via `fetch()` now throw in Node.js as they normally do (not supported by `fetch`).
- Cookies are no longer managed in Node.js for better compatibility. Instead, whatever is the default behavior of your environment that's the cookie behavior you get. This has no effect on the browser.
- WebSocket `connection` life cycle event has been renamed to `websocket:connection` ([#2783](mswjs/msw#2783)).
- `onUnhandledRequest` option has been renamed to `onUnhandledFrame`.
- The library no longer patches `setTimeout` to circumvent fake timers in test runners. You should advance the fake timers normally for delayed mocked responses to resolve.
- The library no longer returns a mocked cookie string on `request.headers.get('cookie')` in the handlers. It returns `null` in all environments. Please use the `cookies` resolver argument to have cookie-based logic.

##### Features

- Supports Node.js v24 and v26.
- Supports TypeScript v6.0 and v7.0.
- You can import individual utilities, like `delay` or `passthrough`, from the new `msw/utils` entrypoint for smaller footprint on your bundle.
- Support GraphQL v17.0.
- Support intercepting page navigations and form submissions ([#2721](mswjs/msw#2721)).
- Support GraphQL subscriptions ([#285](mswjs/msw#285), [#2763](mswjs/msw#2763)).
- Migrate from `path-to-regexp` to `@msw/url` ([#2678](mswjs/msw#2678)).
- Remove the following dependencies:
  - `graphql`
  - `path-to-regexp`
  - `picocolors`
  - `statuses`
  - `strict-event-emitter`
- Adds a Vite plugin for MSW ([#2781](mswjs/msw#2781)).
- Adds a `websocket:error` life cycle event to listen to WebSocket connection errors ([#2784](mswjs/msw#2784)).
- Support modifying the intercepted request headers in passthrough scenarios ([#2786](mswjs/msw#2786)).
- Support a new WebSocket Extension API that allows for better custom experiences ([#2791](mswjs/msw#2791)).

##### Bug fixes

- Fix an issue where preventing a page closure via the `beforeunload` listener would unregister the MSW worker ([#1105](mswjs/msw#1105)).
- Fix an issue that caused intermittent test failures in Vitest Browser Mode and Firefox if using `maxWorkers: 1` ([#2726](mswjs/msw#2726)).
- Fix an issue where in-flight requests were incorrectly passthrough when performed before calling `worker.stop()` ([#2724](mswjs/msw#2724), [#2597](mswjs/msw#2597)).
- Fix an issue where persisting cookies in `localStorage` would cause a maximum quota exceeded errors.
- Fix various issues related to the network interception in Node.js.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant