1.47.0 CJS output uses require_<name> identifiers that collide with esbuild's __commonJS wrapper naming
Since `1.47.0`, the CommonJS files under `dist/compat/` declare their imports using identifiers prefixed with `require_`, e.g.:
```js
// es-toolkit/dist/compat/object/get.js (1.47.0)
const require_isUnsafeProperty = require("../../_internal/isUnsafeProperty.js");
const require_isDeepKey = require("../_internal/isDeepKey.js");
const require_toKey = require("../_internal/toKey.js");
const require_toPath = require("../util/toPath.js");
```
esbuild names the wrapper functions it generates for CommonJS modules in exactly the same form — `require_<basename>`. When this file is processed by esbuild (which is what Vite, tsup, and many others use),
the `const require_isUnsafeProperty` declaration hoists over esbuild's generated wrapper of the same name. The subsequent call therefore resolves to the hoisted `undefined`, throwing:
```
Uncaught TypeError: require_isUnsafeProperty is not a function
```
(After production minification the same bug surfaces as `t is not a function`, since the colliding pair gets mangled to the same short name.)
## Regression
`1.46.1` and earlier used neutral identifier names, which don't collide:
```js
// es-toolkit/dist/compat/object/get.js (1.46.1)
const isUnsafeProperty = require('../../_internal/isUnsafeProperty.js');
```
Downgrading to `1.46.1` (via npm `overrides`) restores correct behaviour.
## Reproduction
Any Vite project that transitively pulls in `es-toolkit/compat/get` will trip this. The fastest path is via `recharts >= 3.x`, which deep-imports it from `recharts/es6/util/DataUtils.js`:
```js
import get from 'es-toolkit/compat/get';
```
Minimal repro:
1. `npm create vite@latest est-bug -- --template react`
2. `npm i recharts es-toolkit@1.47.0`
3. Import any Recharts component in `App.jsx`
4. `npm run dev` → page errors out with `require_isUnsafeProperty is not a function`
5. Add `"overrides": { "es-toolkit": "1.46.1" }` to `package.json`, reinstall → fixed
Tested on Vite 8.0.12, Node 24.
## Why deep imports hit this
The `exports` map at `./compat/*` only exposes the CJS `.js` file:
```json
"./compat/*": {
"types": "./compat/*.d.ts",
"default": "./compat/*.js"
}
```
There's no `"import"` condition pointing to the matching `.mjs` file (which already exists in `dist/` and uses normal ESM imports without the `require_` collision). So ESM consumers who deep-import are forced
through the broken CJS path.
The non-deep `./compat` entry does have an `"import"` condition, so `import { get } from 'es-toolkit/compat'` works correctly.
## Suggested fix (either is sufficient)
1. **Rename the CJS local identifiers** back to neutral names (i.e. drop the `require_` prefix) so they don't collide with esbuild's wrapper naming convention.
2. **Add an `"import"` condition to the `./compat/*` (and any similarly affected `./*/*`) exports** pointing at the existing `.mjs` files, so ESM consumers get the ESM build for deep imports.
Either alone fixes the bug. Option 2 is the more thorough fix because it also benefits tree-shaking for ESM consumers.
关闭于 2026-05-31 4 条评论