tsdown
tsdown — Library Bundler
Blazing-fast bundler for TypeScript/JavaScript libraries powered by Rolldown and Oxc. A modern replacement for tsup.
Setup
npm install -D tsdown
# Or scaffold a new project
npm create tsdown@latest
Requires Node.js 20.19+.
Basic Configuration
// tsdown.config.ts
import { defineConfig } from "tsdown";
export default defineConfig({
entry: ["src/index.ts"],
format: ["esm", "cjs"],
dts: true,
});
Defaults (Different from tsup)
| Option | tsdown default | tsup default |
|---|---|---|
format |
esm |
cjs |
clean |
true |
false |
dts |
Auto-enabled if types field exists in package.json |
false |
Entry Points
// Single entry
entry: ["src/index.ts"],
// Named entries
entry: {
index: "src/index.ts",
utils: "src/utils.ts",
cli: "src/cli.ts",
},
// Glob with exclusions
entry: ["src/**/*.ts", "!**/*.test.ts"],
Output Formats
// Dual ESM + CJS (most common for libraries)
format: ["esm", "cjs"],
// Browser global
format: ["iife"],
globalName: "MyLib",
// UMD for CDN/script tag compatibility
format: ["umd"],
globalName: "MyLib",
Package.json Exports
Auto-generate the exports field:
export default defineConfig({
entry: ["src/index.ts"],
format: ["esm", "cjs"],
dts: true,
exports: true, // auto-generates package.json exports field
});
Type Declarations
// Basic — generates .d.ts alongside output
dts: true,
// With options
dts: {
sourcemap: true,
compilerOptions: {
composite: false,
},
},
Always enable dts for published TypeScript libraries.
Dependency Handling
tsdown automatically externalizes dependencies and peerDependencies from package.json.
// Manually external
external: ["react", "react-dom", /^@myorg\//],
// Force-bundle a dependency (inline it)
noExternal: ["tiny-utility-to-inline"],
- External by default:
dependencies,peerDependencies. - Bundled by default:
devDependencies.
Platform and Target
// Node.js library (default)
platform: "node",
target: "es2022",
// Browser library
platform: "browser",
target: "es2020",
// Isomorphic
platform: "neutral",
Minification
// Full minification
minify: true,
// Dead code elimination only (smaller output, readable)
minify: "dce-only",
Shims
Add ESM/CJS interop shims (__dirname, __filename, import.meta.url):
shims: true,
Enable when publishing dual ESM/CJS packages that reference Node.js globals.
Source Maps
sourcemap: true, // external .map files
sourcemap: "inline", // embedded in output
sourcemap: "hidden", // generated but not referenced
Unbundle Mode
Preserve the source directory structure instead of bundling into a single file:
export default defineConfig({
entry: ["src/**/*.ts", "!**/*.test.ts"],
unbundle: true,
format: ["esm"],
dts: true,
});
Useful for utility libraries where consumers may want to import individual modules.
Plugins
tsdown supports Rolldown, Rollup, and unplugin plugins:
import { wasm } from "rolldown-plugin-wasm";
export default defineConfig({
entry: ["src/index.ts"],
plugins: [wasm()],
});
Multiple Configurations
Export an array for different build targets:
export default defineConfig([
{
entry: ["src/index.ts"],
format: ["esm", "cjs"],
dts: true,
},
{
entry: ["src/cli.ts"],
format: ["esm"],
platform: "node",
banner: { js: "#!/usr/bin/env node" },
},
]);
Conditional Configuration
export default defineConfig((options) => {
const isDev = options.watch;
return {
entry: ["src/index.ts"],
format: ["esm", "cjs"],
minify: !isDev,
sourcemap: isDev,
};
});
Monorepo / Workspace Builds
Build all packages in a monorepo from a single config:
export default defineConfig({
workspace: "packages/*",
entry: ["src/index.ts"],
format: ["esm", "cjs"],
dts: true,
});
Lifecycle Hooks
export default defineConfig({
entry: ["src/index.ts"],
hooks: {
"build:before": async (context) => {
// Pre-build tasks (codegen, validation)
},
"build:done": async (context) => {
// Post-build tasks (copy files, notifications)
},
},
});
CI Configuration
Use 'ci-only' and 'local-only' to vary behavior by environment:
export default defineConfig({
entry: ["src/index.ts"],
format: ["esm", "cjs"],
dts: true,
failOnWarn: "ci-only", // fail on warnings in CI only
publint: "ci-only", // validate package structure in CI
attw: "ci-only", // check "are the types wrong" in CI
});
Common Recipes
React Component Library
export default defineConfig({
entry: ["src/index.tsx"],
format: ["esm", "cjs"],
dts: true,
external: ["react", "react-dom"],
});
Node.js CLI Tool
export default defineConfig({
entry: ["src/cli.ts"],
format: ["esm"],
platform: "node",
target: "es2022",
banner: { js: "#!/usr/bin/env node" },
minify: true,
});
Dual Package with Shims
export default defineConfig({
entry: ["src/index.ts"],
format: ["esm", "cjs"],
dts: true,
shims: true,
exports: true,
clean: true,
});
Migration from tsup
npx tsdown migrate
This handles ~90% of config conversion automatically. Key differences to review:
formatdefaults toesm(tsup defaults tocjs).cleanis enabled by default.dtsauto-enables iftypesfield exists inpackage.json.onSuccess→ usehooks['build:done']instead.splitting→ enabled by default, usesplitting: falseto disable.
CLI Reference
tsdown # Build with defaults
tsdown --watch # Watch mode
tsdown --format esm,cjs # Specify formats
tsdown --dts # Generate declarations
tsdown --minify # Minify output
tsdown --outDir lib # Custom output directory
tsdown --sourcemap # Generate source maps
tsdown --config custom.ts # Custom config file
tsdown src/a.ts src/b.ts # Multiple entries
More from grahamcrackers/skills
bulletproof-react-patterns
Bulletproof React architecture patterns for scalable, maintainable applications. Covers feature-based project structure, component patterns, state management boundaries, API layer design, error handling, security, and testing strategies. Use when structuring a React project, designing application architecture, organizing features, or when the user asks about React project structure or scalable patterns.
44react-aria-components
React Aria Components patterns for building accessible, unstyled UI with composition-based architecture. Covers component structure, styling with Tailwind and CSS, render props, collections, forms, selections, overlays, and drag-and-drop. Use when building accessible components, using react-aria-components, creating design systems, or when the user asks about React Aria, accessible UI primitives, or headless component libraries.
15clean-code-principles
Clean code principles for readable, maintainable TypeScript and React codebases. Covers naming, functions, abstraction, composition, error handling, comments, and code smells. Use when writing new code, refactoring, reviewing code quality, or when the user asks about clean code, readability, or maintainability.
10typescript-best-practices
Core TypeScript conventions for type safety, inference, and clean code. Use when writing TypeScript, reviewing TypeScript code, creating interfaces/types, or when the user asks about TypeScript patterns, conventions, or best practices.
9tanstack-query
TanStack Query v5 patterns for server state management, caching, mutations, optimistic updates, and query organization. Use when working with TanStack Query, React Query, server state, data fetching hooks, or when the user asks about caching strategies, query invalidation, or mutation patterns.
8git-conventions
Git conventions for teams including conventional commits, branching strategies, PR workflows, merge strategies, and commit message formatting. Use when writing commit messages, creating branches, setting up Git workflows, or when the user asks about Git conventions, commit formats, branching strategies, or PR best practices.
7