Skip to content

Replace build tooling with tsdown for dual CJS/ESM output - #82

Open
ikrbasak wants to merge 1 commit into
oculus42:developfrom
ikrbasak:feat/tsdown-bundling
Open

Replace build tooling with tsdown for dual CJS/ESM output#82
ikrbasak wants to merge 1 commit into
oculus42:developfrom
ikrbasak:feat/tsdown-bundling

Conversation

@ikrbasak

@ikrbasak ikrbasak commented Mar 27, 2026

Copy link
Copy Markdown

Problem

The current build pipeline uses tsc directly, which has several issues:

1. No ESM output

tsc emits only CommonJS. Modern bundlers (webpack, rollup, esbuild, vite) and Node.js
with "type": "module" can't tree-shake or properly consume the package without an ESM
build. There is no exports field or module field, so bundlers fall back to the CJS
bundle and lose the ability to do dead-code elimination.

2. Broken type declarations

package.json had "typings": "index.d.ts" pointing to a root-level file that doesn't
exist in the published package — the actual declarations were emitted to dist/.
TypeScript consumers would get no types unless they happened to find them via other means.

3. Tests import internal build artifacts

test/index.js imported validateUUID directly from ../dist/validate, coupling tests
to the internal module structure of the build output. This breaks whenever the bundler
changes how it splits or names output chunks.

4. No files field

Without it, npm publish includes source files, TypeScript sources, config files, and
other noise in the published tarball.


Fix

Replaces tsc with tsdown (built on rolldown) as the
bundler:

  • Emits both CJS (dist/index.js) and ESM (dist/index.mjs) builds from the
    same TypeScript source
  • Generates type declarations for both formats (dist/index.d.ts / dist/index.d.mts)
  • Adds a proper exports map so Node.js and bundlers resolve the right format
    automatically
  • Adds "module" field for bundlers that use it (webpack 4, rollup, etc.)
  • Fixes "typings""types" pointing to the correct generated file in dist/
  • Separates type-checking (tsc --noEmit as prebuild) from bundling, so the build step
    stays fast while type errors are still caught
  • Adds a files field to keep the published package clean
  • Inlines validateUUID into the test file with a regex, removing the dependency on
    internal build artifact paths

Why tsdown

tsdown is a TypeScript-first bundler built on rolldown (Rust-based), designed specifically
for library publishing. It handles the CJS/ESM dual-build, declaration generation, and
exports field wiring with minimal config compared to alternatives like tsup or a
hand-rolled rollup setup.


Changes at a glance

File What changed
package.json tsctsdown; added exports, module, types, files; fixed typings
tsdown.config.mjs New bundler config: CJS + ESM output, dts, inline sourcemaps, minification
test/index.js Removed ../dist/validate import; inlined UUID regex; guarded constants.default
package-lock.json Lockfile updated with tsdown and its dependencies

Adds tsdown bundler config with proper CJS/ESM dual packaging, TypeScript
declarations, inline sourcemaps, and minification. Updates package.json
exports map and test imports accordingly.
@ikrbasak
ikrbasak marked this pull request as ready for review March 27, 2026 03:47
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.

1 participant