HomeGuidesHow to Package and Publish Modern TypeScript npm Libraries with tsup
Developer Tools7 min readUpdated 2026-11-06

How to Package and Publish Modern TypeScript npm Libraries with tsup

Configure dual ESM and CJS exports maps, generate TypeScript declaration files (.d.ts), and automate npm registry publishing.

Need to do this immediately?

Use our free, private client-side browser tool with zero installation.

View package.json Cheat Sheet
Publishing a modern TypeScript library in the JavaScript ecosystem is notoriously tricky. Consumers might use native ES Modules (`import`), legacy Node CommonJS (`require`), or Next.js Bundlers. Here is how to configure a bulletproof dual-package library using `tsup` in minutes.

Why tsup is the Gold Standard for Library Bundling

Built on top of esbuild, `tsup` compiles TypeScript into both ESM (`.mjs`) and CommonJS (`.cjs`) in milliseconds without requiring convoluted Rollup or Webpack configurations.

Crucially, `tsup` automatically runs the TypeScript compiler in the background to generate clean declaration files (`.d.ts`), giving consumers full autocomplete and type safety.

Pro Tip:Always declare "sideEffects": false in package.json to enable tree-shaking for library consumers.

The Modern Subpath Exports Map

Legacy npm packages used `main` and `module` fields. Modern Node.js versions require the `exports` map, which defines strict entry points and prevents consumers from importing private internal files.

Inside the `exports` object, the `types` condition MUST always be listed first, followed by `import` and `require`.

Step-by-Step Tutorial

1

Install tsup as a devDependency

Run `npm install -D tsup typescript` in your library project root.

2

Define tsup Build Script in package.json

Add `"build": "tsup src/index.ts --format cjs,esm --dts --clean"` to compile dual formats with types.

3

Configure package.json Exports Field

Point `types` to `./dist/index.d.ts`, `import` to `./dist/index.mjs`, and `require` to `./dist/index.cjs`.

Ready to Try It Yourself?

DocSwift processes everything directly on your device. Fast, safe, and completely free forever.

How helpful was this guide?

Rated 4.9 / 5 by 3,420+ users worldwide

Share with Colleagues & Friends

Help others protect their document privacy

Frequently Asked Questions

Why must "types" come first in the exports map?

TypeScript resolver parses exports conditions in strict order. If "import" is listed before "types", TypeScript may attempt to parse the JavaScript file instead of the declaration file, breaking types.

How do I test my package locally before publishing to npm?

Run `npm pack` to generate a `.tgz` tarball, then install it in another test project with `npm install /path/to/package.tgz`. This simulates exact npm installation behavior.