babel / babel/babel-polyfills

Babel/core-js URL polyfill breaks Webpack's new URL() for Web Workers

Open
#240 5 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
357
Forks
62
PR merge metrics
No merged PRs in 30d

Description

When `@babel/preset-env` targets an older browser environment (e.g., `chrome >= 52`) that lacks native support for the `new URL(..., import.meta.url)` syntax, it injects a polyfill for the `URL` constructor from `core-js`. This polyfilled URL constructor interferes with Webpack's static analysis for Web Workers, which specifically looks for the new URL(...) pattern.

As a result, Webpack fails to create a separate chunk for the worker. Instead, the `core-js` polyfill is invoked with an incorrect, non-functional path, causing the worker instantiation to fail at runtime.

## Environment

* **`@babel/core`**: `^7.24.7`
* **`@babel/preset-env`**: `^7.24.7`
* **`webpack`**: `^5.91.0`
* **`babel-loader`**: `^9.1.3`
* **`core-js-pure`**: `^3.43.0`
* **`babel-plugin-polyfill-corejs3`**: `^0.12.0`

#### Steps to Reproduce

A full reproduction repository is available here: **https://github.com/gregaou/example-babel-polyfill-workers**

1. Clone the repository.
2. Ensure the `.browserslistrc` file targets an older browser:
```
chrome >= 52
```
3. Install dependencies (`npm install` or `yarn`).
4. Run the build (`npm run build` or `yarn build`).
5. Inspect the generated output in `dist/`.

#### Expected Behavior

When targeting a modern browser like `chrome >= 67` (where `new URL(..., import.meta.url)` is natively supported), Babel does not polyfill `URL`. Webpack correctly identifies the syntax and generates a functional worker loader:

```javascript
// Correct output for modern targets
const newFibWorker = new Worker(new URL(/* worker import */ __webpack_require__.p + __webpack_require__.u("src_worker_ts-_..."), __webpack_require__.b));
```

This code works as expected.

#### Actual Behavior

When targeting `chrome >= 52`, `@babel/preset-env` injects the `core-js` polyfill for `URL`. The resulting code in the bundle looks like this:

```javascript
// Incorrect output for older targets
const newFibWorker = new Worker(new (core_js_pure_stable_url_index_js__WEBPACK_IMPORTED_MODULE_2___default())('./worker.ts', "file:///.../src/index.tsx"));
```

This fails at runtime because:
1. The `new URL(...)` syntax that Webpack's parser looks for has been replaced.
2. The `core-js` polyfill is invoked with a file-system path (`import.meta.url` is transpiled to a file path), which is not a valid base for creating a worker URL in the browser.

Contributor guide

Open the contributing guide

Research direction

Clone the linked reproduction repository, inspect its .browserslistrc and the build output in dist/ after targeting chrome >= 52. Compare the transformed worker expression with the chrome >= 67 output, then trace the Babel polyfill behavior and Webpack worker entry-point detection. Done means the older-target build preserves Webpack's worker chunk generation and the worker loads successfully at runtime.

Written by the indexing model from the issue text.

Assessment

Tech stack
babel, typescript, webpack
Domain
build-system, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.