What it is
tsup bundles TypeScript libraries with almost no configuration, producing ESM and CommonJS output plus declaration files in one command.
Point tsup at an entry file and specify the formats. It handles bundling, minification, declaration generation and tree-shaking metadata.
Installation
npm install -D tsupGetting started
The smallest useful thing you can do with it, and what each part means.
// tsup.config.ts
import { defineConfig } from 'tsup';
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true, // emit .d.ts
sourcemap: true,
clean: true,
treeshake: true,
});{
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"require": "./dist/index.cjs"
}
},
"files": ["dist"]
}Advanced usage
Where the library earns its place over a simpler alternative.
export default defineConfig({
entry: { index: 'src/index.ts', cli: 'src/cli.ts' },
format: ['esm'],
external: ['react', 'react-dom'], // never bundle peer dependencies
banner: { js: '#!/usr/bin/env node' },
onSuccess: 'node dist/cli.js --smoke-test',
});Errors and fixes
The failures you are most likely to hit, and what actually resolves them.
- Consumers see any for your types
- The types condition is missing or ordered after import/require in exports. It must be first.
- Two copies of React at runtime
- React was bundled instead of externalised. Add it to external and to peerDependencies.
Best practices
- Mark every peer dependency as external — bundling React or Vue breaks consumers.
- Put the types condition first in package.json exports.
- Disable dts in watch mode; it dominates build time.
- Use tsup for libraries and Vite for applications — they solve different problems.
Background
Why it exists, and what it was reacting to.
Built on esbuild by Kane Wallmann and egoist, tsup exists because publishing a dual-format npm package used to require a rollup config, a tsc pass and careful package.json exports — work that is nearly identical for every library.
