Skip to content

fix: publish a single-file ESM bundle that Node can load (4.1.6) - #241

Merged
Johan Gorter (johan-gorter) merged 2 commits into
mainfrom
fix/esm-entry
Oct 12, 2026
Merged

Johan Gorter (johan-gorter) merged 2 commits into
mainfrom
fix/esm-entry

Conversation

@johan-gorter

Copy link
Copy Markdown
Contributor

Fixes #240.

Problem

Since 4.1.4, exports["."].import points at dist/index.js. That file comes straight from tsc and keeps its extensionless relative imports (./cache, ./dom, …), so Node, Vitest and Jest ESM all fail with ERR_MODULE_NOT_FOUND. The type declarations have the same problem: attw reported an internal resolution error for node16 and "Masquerading as ESM" for node16 from CJS.

Changes

  • rollup: also emits dist/maquette.mjs (ES format, with sourcemap) from dist/index.js, next to the existing CJS and UMD bundles.
  • Types: rollup-plugin-dts bundles the declarations into dist/maquette.d.mts and dist/maquette.d.cts, so ESM and CJS consumers each get correctly typed single-file declarations. This goes beyond the issue, but attw cannot pass without it.
  • package.json
    • exports["."]: import → { types: maquette.d.mts, default: maquette.mjs }, require → { types: maquette.d.cts, default: maquette.cjs }.
    • Removed the browser condition, so bundlers get the ESM bundle instead of UMD. dist/maquette.umd.js / .min.js are still published for <script> use.
    • Added "sideEffects": false.
    • main and types are unchanged.
    • Version bumped to 4.1.6.
  • CI: new check-package script, run at the end of npm run ci:
    • attw --pack . reports no problems for node10, node16 (CJS and ESM) and bundler.
    • tools/check-package-loads.ts packs the package, installs the tarball in a temp directory and loads it from Node through both import and require. If I point import back at dist/index.js, this check fails with the exact error from the issue.

Verification

npm run ci passes locally: lint, 95 tests, file-size check (3.65 kB gzipped), attw and the smoke test.

Follow-up

After 4.1.6 is published, remove the 4.1.3 pin and the Dependabot ignore for maquette in the Focus repo.

🤖 Generated with Claude Code

dist/index.js (the "import" entry since 4.1.4) contains extensionless
relative imports, which Node's ESM loader cannot resolve. Let rollup
produce dist/maquette.mjs next to the CJS and UMD bundles, and bundle
the type declarations into dist/maquette.d.mts / dist/maquette.d.cts so
types resolve for node16 ESM and CJS as well.

- exports: import -> maquette.mjs, require -> maquette.cjs, each with
  its own types; drop the "browser" condition so bundlers get ESM
- add "sideEffects": false
- add check-package (attw + a smoke test that installs the packed
  tarball and loads it via import and require) to the ci script
- bump to 4.1.6

Fixes #240

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 12, 2026 07:13

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The lockfile still identifies the root package as version 4.1.5 rather than 4.1.6.

0 open findings

What changed in this PR

Publishes Node-compatible single-file ESM/CJS bundles with matching bundled declarations and package validation.

Changes:

  • Adds ESM and declaration bundling.
  • Updates package exports and release metadata.
  • Adds CI package-loading and type-resolution checks.
File Description
rollup.config.js Adds ESM and declaration bundles.
package.json Updates exports, scripts, dependencies, and version.
package-lock.json Locks new tooling dependencies.
tools/​check-package-loads.ts Smoke-tests ESM and CJS package loading.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@johan-gorter
Johan Gorter (johan-gorter) merged commit 8c73f7d into main Oct 12, 2026
6 checks passed
@johan-gorter
Johan Gorter (johan-gorter) deleted the fix/esm-entry branch October 12, 2026 08:30
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.

ESM entry (dist/index.js) has extensionless imports and cannot be loaded by Node

3 participants