Babel/core-js URL polyfill breaks Webpack's new URL() for Web Workers
- 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
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