Dual ESM/CJS Package
Publishing & TypeScript
Master dual-format npm publishing, conquer the dual-package hazard, optimise tree-shaking, and configure TypeScript for production-grade library distribution.
Why dual-format publishing matters
JavaScript's module ecosystem is split between CommonJS (CJS) — the legacy synchronous format powering decades of Node.js tooling — and ECMAScript Modules (ESM), the modern static format that enables tree-shaking, top-level await, and native browser support. Library authors must ship both to avoid breaking consumers.
A misconfigured package.json exports field can silently instantiate your
library twice in the same process, corrupting singleton state and breaking framework registries.
Getting this right requires understanding resolution mechanics, TypeScript declaration alignment,
and bundler-specific behaviour.
This site is a practical reference covering every layer of the stack — from Node.js module caches and conditional exports to tsconfig settings, build tooling, and CI validation pipelines.
What you'll learn
- How ESM and CJS execution models differ at runtime
- The exact
exportsfield pattern that prevents dual-package hazards - Tree-shaking: why
sideEffects: falseisn't enough on its own - Barrel file anti-patterns and how they destroy bundle optimisation
- tsconfig options for library authors (
moduleResolution: "bundler", declaration maps) - Build tooling: tsup, esbuild, Rollup for dual ESM/CJS output
- CI/CD matrix testing across ESM and CJS consumer harnesses
Explore the Guides
ESM vs CJS execution models, Node.js resolution mechanics, the dual-package hazard,
and mastering the package.json exports field.
- Understanding ESM vs CJS
- Navigating the Dual-Package Hazard
- Mastering the exports Field
- Browser vs Node.js Resolution
Dead code elimination, sideEffects flag configuration, barrel file anti-patterns,
and measuring real bundle impact.
- Implementing sideEffects Correctly
- Eliminating Barrel File Anti-Patterns
- Advanced DCE Techniques
- Optimising Bundle Size
tsconfig for library distribution, declaration file generation, path aliases, and modern build tools — tsup, esbuild, and Rollup.
Explore section →