ITADN

1.47.0 CJS output uses require_<name> identifiers that collide with esbuild's __commonJS wrapper naming

#1740Closedgom59 创建于 2026-05-26
G
gom59commented
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 条评论