grahamcrackers/skills

tsdown

tsdown patterns for bundling TypeScript and JavaScript libraries powered by Rolldown.

First seen Feb 25, 2026

Installation

$ npx skills add grahamcrackers/skills --skill tsdown

Summary

  • tsdown patterns for bundling TypeScript and JavaScript libraries powered by Rolldown.
  • Covers configuration, output formats, type declarations, dependency handling, plugins, monorepo builds, and migration from tsup.
  • Use when building libraries, generating type declarations, bundling for multiple formats, configuring tsdown, or migrating from tsup.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from grahamcrackers/skills · top by installs.

npx skills add grahamcrackers/skills

Browse all from grahamcrackers/skills

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

License LICENSE
Default branch main
Open issues 0
Status Active

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 7,184 B
  • docs SUMMARY.md 362 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 8 installs

SKILL.md

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:

  • format defaults to esm (tsup defaults to cjs).
  • clean is enabled by default.
  • dts auto-enables if types field exists in package.json.
  • onSuccess → use hooks['build:done'] instead.
  • splitting → enabled by default, use splitting: false to 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