Skip to content

feat(scripts): add support for .mjs and .d.mts exports in compat module - #1199

Merged
dayongkr merged 2 commits into
mainfrom
esm-compat
Jun 7, 2025
Merged

dayongkr merged 2 commits into
mainfrom
esm-compat

Conversation

@dayongkr

@dayongkr dayongkr commented Jun 6, 2025

Copy link
Copy Markdown
Collaborator

Although the main environment is CommonJS (CJS), since some environments like testing use ESM, we're adding ESM files under the compat/* path to support dual module paths.

@dayongkr
dayongkr requested a review from raon0211 as a code owner June 6, 2025 08:09
@vercel

vercel Bot commented Jun 6, 2025 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
es-toolkit ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 6, 2025 8:19am

@codecov-commenter

codecov-commenter commented Jun 6, 2025 •

Copy link
Copy Markdown

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 99.51%. Comparing base (8271527) to head (9387b8f).

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##             main    #1199   +/-   ##
=======================================
  Coverage   99.51%   99.51%           
=======================================
  Files         457      457           
  Lines        4339     4339           
  Branches     1286     1286           
=======================================
  Hits         4318     4318           
  Misses         21       21           
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@dayongkr
dayongkr merged commit f6e1ce3 into main Jun 7, 2025
raon0211 pushed a commit that referenced this pull request Jun 7, 2026
The `./compat/*` wildcard export only declared a CJS `default`
condition, so `import get from "es-toolkit/compat/get"` always
resolved to a CommonJS stub even in fully-ESM graphs. Every other
subpath already splits `import`/`require`; compat alone shipped CJS to
ESM importers, costing interop wrappers and worse tree-shaking.

This was uncovered by a rolldown (vite 8) chunk-rendering bug where
the dist `require_*` helper naming crashed production builds
(rolldown#9653) — but that bug is now fixed upstream, so it is not the
motivation here. The motivation is the independent, measurable cost of
shipping CJS to ESM consumers, which stands regardless of any bundler.

Generate `.mjs` (ESM) stubs and `.d.mts` types alongside the existing
`.js`/`.d.ts` in postbuild, and split `./compat/*` into `import` /
`require` conditions like every other subpath. ESM importers now
resolve to pure-ESM `.mjs` (zero `require(` in the chain); `require`
still gets CJS. attw `node16 (from ESM)` goes from "Incorrect default
export" to "OK (ESM)".

Package size impact (measured via `npm pack`; dist/ is byte-identical
between old and new — the ESM implementations already ship either way,
this only adds tiny one-line re-export stubs):

    metric            OLD (CJS)   NEW (+ESM)   delta
    tarball (gzip)    645.5 KB    670.0 KB     +24.5 KB (+3.8%)
    unpacked          3.33 MB     3.37 MB      +0.04 MB (+1.2%)
    file count        3018        3612         +594 (297 fns x 2)

Smaller consumer bundles. Bundled small ESM apps that deep-import
compat functions with esbuild (bundle + tree-shake + minify) against
the old and new packages and compared output bytes:

    import set                       OLD (CJS)   NEW (ESM)   reduction
    get + maxBy                      11,602 B    8,122 B     -30.0%
    recharts 3's 11 deep-imports     21,526 B    15,193 B    -29.4%

Timeline:
  2025-06-07  #1199 (f6e1ce3) added this exact change (.mjs/.d.mts
              stubs + import/require split) to support ESM consumers.
  2025-06-15  e6f6762 reverted it ("Provide compat/* in CommonJS
              format by default") — direct push to main, no PR, no
              rationale in the message.
  2025-10-18  #1479 reported `exports is not defined` and proposed
              this identical fix. Closed; maintainer rationale was
              package size + "importing CJS from ESM is fine."
  2026-06-05  #1756 filed. The triggering rolldown bug is fixed
              upstream, but it surfaced that compat/* ships CJS to ESM
              importers — independently worth fixing (size, resolution,
              tree-shaking) per the measurements above.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

This branch was successfully deployed

1 active deployment
Preview — 9387b8f6 Deployed Jun 6, 2025 by vercel[bot]
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.

2 participants