tsup logo

tsup

基于 esbuild 的零配置 TypeScript 库打包工具——最快将 TypeScript 项目打包发布为 npm 包的方案之一。

精选工具BundleresbuildTypeScript零配置

tsup 是基于 esbuild 的零配置 TypeScript 库打包工具,一条命令即可完成 ESM + CJS 双格式输出和 .d.ts 类型声明生成,是 TypeScript 库打包领域最受欢迎的工具之一。

tsup

基于 esbuild 的零配置 TypeScript 库打包工具——最快将 TypeScript 项目打包发布为 npm 包的方案之一。

技术简介说明

tsup 是由 EGOIST(egoist)开发的一款专注于 TypeScript 库打包的构建工具。它底层基于 esbuild(使用 Go 语言编写的超高速 JavaScript/TypeScript 打包器),为开发者提供了"零配置"的打包体验。tsup 的核心设计目标只有一个:让你用最简单、最快的方式将 TypeScript 库打包并发布到 npm

与 Webpack、Rollup 这类通用型打包工具不同,tsup 专门为库(library)开发者设计。它开箱即支持 ESM 和 CJS 双格式输出、自动 .d.ts 类型声明文件生成、代码拆分(code splitting)、Tree Shaking、Source Map、Watch 模式等现代库开发所需的全部能力。开发者只需一条命令、甚至不需要任何配置文件,就能完成从 TypeScript 源码到可发布 npm 包的全流程。

tsup 自发布以来迅速成为 TypeScript 库打包领域最受欢迎的工具之一,周下载量超过 560 万次,GitHub 星标超过 11,300 个。包括 shadcn/ui CLI、novel.sh 等知名开源项目都采用了 tsup 作为其构建工具。然而,2025 年下半年,作者宣布该项目不再活跃维护,并推荐使用继任者 tsdown(基于 Rolldown/Rust 构建)。

基本信息

  • 官网https://tsup.egoist.dev/
  • GitHubhttps://github.com/egoist/tsup
  • License:MIT
  • 最新版本:v8.5.1(2025 年 11 月 12 日发布)
  • 主要维护者/公司:EGOIST(egoist)——独立开发者,同时也是 Vue.js 生态中多个知名工具的作者
  • npm 周下载量:约 560 万次(截至 2026 年初)
  • GitHub Stars:约 11,300+
  • 语言构成:98.8% TypeScript

快速上手

安装

推荐使用本地安装方式(作为开发依赖),不建议全局安装:

# npm
npm install tsup -D
 
# yarn
yarn add tsup -D
 
# pnpm(推荐)
pnpm add tsup -D

同时需要确保项目中已安装 TypeScript:

pnpm add typescript -D

基础配置

tsup 的核心理念是"零配置",但也可以通过配置文件或 CLI 参数自定义行为。

CLI 方式(最简使用)

# 直接打包,输出到 ./dist 目录
npx tsup src/index.ts
 
# 同时打包多个入口
npx tsup src/index.ts src/cli.ts
 
# 指定输出格式
npx tsup src/index.ts --format esm,cjs,iife
 
# 开启类型声明文件生成
npx tsup src/index.ts --dts
 
# 监听模式
npx tsup src/index.ts --watch
 
# 代码压缩
npx tsup src/index.ts --minify
 
# 清理输出目录
npx tsup src/index.ts --clean

配置文件方式(推荐用于项目)

在项目根目录创建 tsup.config.ts(也支持 tsup.config.jstsup.config.ctstsup.config.mts):

import { defineConfig } from 'tsup'
 
export default defineConfig({
  // 入口文件
  entry: ['src/index.ts'],
  // 输出格式
  format: ['esm', 'cjs'],
  // 生成 .d.ts 类型声明文件
  dts: true,
  // 代码拆分
  splitting: true,
  // 代码压缩
  minify: false,
  // Source Map
  sourcemap: true,
  // 清理输出目录
  clean: true,
  // 目标环境
  target: 'es2020',
  // 外部依赖(不打包)
  external: ['react', 'react-dom'],
  // 输出目录,默认 dist
  outDir: 'dist',
})

package.json 配置

{
  "name": "my-awesome-lib",
  "version": "1.0.0",
  "main": "./dist/index.cjs",
  "module": "./dist/index.js",
  "types": "./dist/index.d.ts",
  "exports": {
    ".": {
      "import": {
        "types": "./dist/index.d.mts",
        "default": "./dist/index.js"
      },
      "require": {
        "types": "./dist/index.d.cts",
        "default": "./dist/index.cjs"
      }
    }
  },
  "files": ["dist"],
  "scripts": {
    "build": "tsup",
    "dev": "tsup --watch"
  },
  "devDependencies": {
    "tsup": "^8.5.1",
    "typescript": "^5.5.0"
  }
}

tsconfig.json 推荐配置

{
  "compilerOptions": {
    "strict": true,
    "target": "ES2020",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "declaration": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src"],
  "exclude": ["node_modules", "dist"]
}

最小示例

以下是一个最简单的完整示例:

src/index.ts

export function greet(name: string): string {
  return `Hello, ${name}!`
}
 
export const VERSION = '1.0.0'

执行打包

npx tsup src/index.ts --format esm,cjs --dts

输出结果dist/ 目录):

dist/
├── index.js       # ESM 格式
├── index.cjs      # CJS 格式
├── index.d.ts     # 类型声明
└── index.d.cts    # CJS 类型声明

就是这么简单——无需任何配置文件,一条命令即可完成双格式输出 + 类型声明。

核心概念与架构

架构设计

tsup 的架构可以概括为三层:

┌─────────────────────────────────────┐
│           tsup CLI / API            │  ← 用户接口层
├─────────────────────────────────────┤
│        tsup 核心编排层               │  ← 配置解析、任务编排、DTS 生成
├─────────────────────────────────────┤
│            esbuild                  │  ← 底层打包引擎(Go)
└─────────────────────────────────────┘
  1. 用户接口层:提供 CLI 命令和 Node.js API 两种调用方式
  2. 核心编排层:负责解析配置、管理多格式输出、调度 DTS 生成(通过 worker 线程)、文件监听等
  3. 底层引擎层:实际的文件解析、转换、打包由 esbuild 完成

工作原理

  1. 入口解析:根据 entry 配置确定打包入口文件
  2. 依赖图构建:esbuild 解析所有 import/require,构建完整依赖图
  3. 代码转换:通过 esbuild 将 TypeScript/JSX 等转换为 JavaScript
  4. Tree Shaking:移除未使用的代码(dead code elimination)
  5. 格式输出:根据 format 配置输出对应格式(ESM/CJS/IIFE)
  6. DTS 生成:通过独立 worker 线程调用 TypeScript 编译器生成类型声明
  7. 后处理:可选的压缩、Source Map、清理输出目录等

DTS 生成机制

tsup 的类型声明文件生成是一个值得特别说明的机制。它有两种模式:

  • 默认模式dts: true):使用 TypeScript 编译器 API 在独立 worker 线程中生成 .d.ts 文件,不影响主打包流程速度
  • 实验性 DTS 模式experimentalDts: true,v8.0.0+):使用 @microsoft/api-extractor 生成更精确的合并类型声明,减少重复类型导出

核心特性

  • 🚀 极速打包:底层使用 esbuild(Go 实现),比传统基于 Rollup/Webpack 的方案快 10-100 倍。50 个文件打包约 2.5 秒
  • ⚙️ 零配置启动:无需配置文件即可打包 TypeScript 项目,开箱即用
  • 📦 双格式输出:同时输出 ESM 和 CJS 格式,满足所有消费端需求
  • 📝 类型声明生成:通过 dts: true 自动生成 .d.ts 文件,无需单独运行 tsc
  • 🌳 Tree Shaking:自动移除未使用代码,减小包体积
  • 💻 代码拆分:支持 code splitting,将共享模块提取为独立 chunk
  • 👁️ Watch 模式:内建文件监听,修改源码后自动重新构建
  • 🗺️ Source Map:支持生成 Source Map,方便调试
  • 🎨 CSS 支持:实验性 CSS 打包支持(v8.4.0+ 升级了 CSS 编译器)
  • 🔌 插件系统:支持 esbuild 插件生态,可通过 esbuildPlugins 扩展能力
  • 🏷️ 多入口打包:支持多个入口文件同时打包
  • 📋 JSON Schema:提供配置文件的 JSON Schema,支持编辑器自动补全和语法校验
  • 🎯 灵活的目标环境:支持 es5 ~ es2024node10 ~ node22 等多种 target

生态图

核心依赖

依赖作用
esbuild底层打包引擎,提供超高速 JavaScript/TypeScript 转换
typescript用于生成 .d.ts 类型声明文件
bundle-require用于加载 tsup.config.ts 配置文件
sucrase辅助处理某些 TypeScript 特性
globby入口文件 glob 匹配
@microsoft/api-extractorexperimentalDts 模式下的类型合并工具

相关插件/扩展

tsup 的插件系统基于 esbuild 插件,可以直接使用 esbuild 生态中的插件:

import { defineConfig } from 'tsup'
import somePlugin from 'some-esbuild-plugin'
 
export default defineConfig({
  entry: ['src/index.ts'],
  esbuildPlugins: [somePlugin()],
})

常用 esbuild 插件示例:

  • esbuild-fix-imports-plugin:修复文件扩展名、路径别名和目录导入
  • esbuild-plugin-less:Less 预处理器支持
  • esbuild-sass-plugin:Sass 预处理器支持
  • esbuild-style-plugin:CSS Modules 支持

社区生态

  • 知名用户:shadcn/ui CLI、novel.sh、MSW(Mock Service Worker)等
  • 模板/脚手架:社区提供了多种 tsup 项目模板
  • 教程生态:LogRocket、DEV Community、Built In 等技术社区有大量教程
  • 迁移工具:tsdown 提供 npx tsdown-migrate 一键迁移工具

继任者:tsdown

2025 年底,EGOIST 推荐迁移到 tsdown——一个基于 Rolldown(Vite 团队用 Rust 开发的新一代打包器)的继任工具。tsdown 几乎 100% 兼容 tsup 的配置,但提供更好的性能和更多功能。

适用场景

  • npm 库/包开发与发布:tsup 最核心的场景——快速将 TypeScript 库打包为 ESM + CJS 双格式并发布到 npm。零配置 + 极速构建让库开发体验极佳
  • CLI 工具打包:适合打包命令行工具,支持 shebang、多入口、target 指定等。shadcn/ui CLI 就是典型案例
  • Monorepo 中的子包构建:轻量快速,适合 monorepo 中需要独立构建的子包。搭配 --watch 模式可实现开发时实时构建
  • 快速原型/小工具开发:需要快速将 TypeScript 转换为可分发的 JavaScript 包时,tsup 是最省事的选择
  • UI 组件库(轻量场景):对于不需要复杂 CSS 管线和主题系统的轻量 UI 组件库,tsup 足够胜任
  • 教学与开源项目:配置简单、文档清晰,非常适合教学场景和中小型开源项目的构建
  • Serverless/Edge 函数打包:快速打包独立函数,配合 target 指定运行环境

开发与工程化

开发流程

# 开发模式(监听文件变化)
pnpm dev  # 等同于 tsup --watch
 
# 生产构建
pnpm build  # 等同于 tsup
 
# 类型检查(tsup 不做类型检查,需单独运行)
pnpm typecheck  # tsc --noEmit
 
# 测试
pnpm test

重要提示:tsup 只负责代码转换和打包,不做类型检查。类型检查需要单独运行 tsc --noEmit

构建部署

典型 CI/CD 集成(GitHub Actions 示例)

name: Build & Publish
on:
  push:
    tags: ['v*']
 
jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
          registry-url: 'https://registry.npmjs.org'
          cache: 'pnpm'
 
      - run: pnpm install --frozen-lockfile
      - run: pnpm typecheck
      - run: pnpm build
      - run: npx publint  # 验证包发布配置
 
      - run: pnpm publish --no-git-checks
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

工程化最佳实践

  1. 使用 publint 验证发布配置:在 CI 中集成 publint 检查 exports 字段和类型路径是否正确
  2. 使用 are-the-types-wrong:验证发布的类型声明是否能被各种消费端正确解析
  3. peerDependencies 必须标记为 external:避免将 React、Vue 等框架依赖打包进库中
  4. 添加 sideEffects 字段:在 package.json 中正确声明,帮助消费端的打包工具做 Tree Shaking
  5. 分离类型检查与打包:tsup 只做转换,类型检查用 tsc --noEmit
  6. 使用 --clean 标志:生产构建时清理旧的输出文件

性能与安全

性能特点

指标表现
打包速度(50 文件)~2.5 秒
引擎esbuild(Go 多线程)
DTS 生成独立 worker 线程,不阻塞主流程
Watch 模式esbuild 原生增量编译,极快
Monorepo 构建(26 包)~7 秒(tsup)→ ~3.5 秒(tsdown,快 49%)

性能优化建议

  • 将不需要打包的依赖标记为 external
  • 使用 --no-splitting 关闭代码拆分(对于简单库可减少开销)
  • 开发时使用 --watch 而非每次重新构建
  • DTS 生成是整体构建中最慢的环节,可考虑在开发时关闭 dts

安全注意事项

根据 Snyk 安全数据库信息:

  • tsup v8.5.1(最新版本)无已知安全问题
  • v8.2.2 ~ v8.5.0 存在一个中等严重性缺陷
  • 建议使用最新版本并定期运行 npm audit
  • 由于 tsup 是构建时工具(开发依赖),安全风险相对较低——不直接影响运行时

已知安全关注点

  • esbuild 依赖链中的间接依赖可能存在风险
  • onSuccess 回调执行外部命令时需注意命令注入风险
  • 加载 tsup.config.ts 时通过 bundle-require 执行任意 TypeScript 代码

已知性能瓶颈

  1. DTS 生成速度慢:这是所有基于 TypeScript 编译器的类型生成方案的共同瓶颈,与打包引擎无关
  2. Node.js 启动开销:对于小型项目,Node.js 的启动时间可能比打包本身更长
  3. CSS 处理有限:实验性 CSS 支持在复杂场景下可能不够高效
  4. esbuild 功能限制:由于底层使用 esbuild,无法使用 Rollup 生态中的高级优化插件

技术对比

tsup vs 同类工具

特性tsuptsdownunbuildRolluppkgroll
底层引擎esbuild (Go)Rolldown (Rust)Rollup (JS)Rollup (JS)Rollup (JS)
打包速度⚡ 快⚡⚡ 极快🐢 中等🐢 中等🐢 中等
50 文件打包~2.5s~0.6s~4-5s~4-5s~4-5s
零配置⚠️ 需少量配置
ESM + CJS
DTS 生成✅ 实验性✅ 原生支持❌ 需插件
Tree Shaking✅ 更强
Stub 模式
插件生态esbuild 插件Rolldown 插件Rollup 插件Rollup 插件(最丰富)Rollup 插件
维护状态❌ 停止维护✅ 活跃开发✅ 活跃开发✅ 活跃开发✅ 活跃开发
周下载量~560 万~50 万~300 万~2500 万较少

关键差异分析

tsup vs tsdown

  • tsdown 是 tsup 的直接继任者,配置几乎 100% 兼容
  • tsdown 使用 Rolldown(Rust)替代 esbuild(Go),构建速度提升 3-10 倍
  • tsdown 是 ESM-first 设计,原生解决 .mjs/.cjs 扩展名问题
  • tsdown 新增 stub 模式、workspace 支持、CSS 完整管线、独立二进制打包等功能
  • tsdown 的 DTS 生成原生支持 isolatedDeclarations,更可靠

tsup vs unbuild

  • unbuild 基于 Rollup,Tree Shaking 效果更好
  • unbuild 属于 UnJS/Nuxt 生态,与该生态集成更紧密
  • unbuild 的 stub 模式对 monorepo 开发更友好
  • tsup 配置更简单、上手更快

tsup vs Rollup

  • Rollup 是工业级标准打包器,插件生态最丰富
  • tsup 是 Rollup 的高层封装(但底层用 esbuild),专注于库开发场景
  • Rollup 更灵活但需要更多配置

最佳实践

生产环境建议

1. 配置文件最佳实践

import { defineConfig } from 'tsup'
 
export default defineConfig({
  entry: ['src/index.ts'],
  format: ['esm', 'cjs'],
  dts: true,
  splitting: true,
  sourcemap: true,
  clean: true,
  target: 'es2020',
  // 关键:标记 peerDependencies 为外部依赖
  external: ['react', 'react-dom', 'vue'],
  // 忽略测试文件
  ignoreWatch: ['**/*.test.ts', '**/*.spec.ts'],
  // 构建完成后执行检查
  onSuccess: async () => {
    console.log('✅ Build completed')
  },
})

2. 多入口打包

export default defineConfig({
  entry: {
    index: 'src/index.ts',
    cli: 'src/cli.ts',
    'utils/helpers': 'src/utils/helpers.ts',
  },
  format: ['esm', 'cjs'],
  dts: true,
  splitting: true,
})

3. 环境变量替换

import { defineConfig } from 'tsup'
 
export default defineConfig({
  entry: ['src/index.ts'],
  define: {
    'process.env.VERSION': JSON.stringify(process.env.npm_package_version),
  },
})

4. 样式注入

export default defineConfig({
  entry: ['src/index.ts'],
  injectStyle: async (path) => {
    const css = await fs.readFile(path, 'utf-8')
    return `injectStyle(${JSON.stringify(css)})`
  },
})

常见陷阱

  1. 忘记将 peerDependencies 设为 external:导致 React/Vue 等框架被打包进库中,产生运行时错误
  2. 混淆类型检查与打包:tsup 不检查类型错误,需要单独运行 tsc --noEmit
  3. bundle: false 使用不当:如果不需要打包(只想转译),应使用 --no-bundle 而非逐个添加 external
  4. 忽略 exports 字段校验:发布前务必用 publint 检查,避免消费端解析失败
  5. DTS 生成遗漏边界情况:复杂的泛型、条件类型可能在 .d.ts 中出错,需人工检查输出

推荐模式

  • 小型工具库:单入口 + ESM/CJS 双格式 + DTS
  • 组件库:多入口 + code splitting + external 框架依赖
  • CLI 工具:单独入口 + shebang 支持 + target 指定 Node.js 版本
  • Monorepo:每个子包独立 tsup 配置 + watch 模式并行开发

技术局限与边界

已知限制

  1. 不再活跃维护:2025 年下半年,作者宣布 tsup 不再积极维护。虽然现有版本仍然可用,但不会收到新的功能更新和及时的 bug 修复
  2. 底层 esbuild 的功能限制
    • 不支持 Rollup 的 output.intro/output.outro 等高级包装选项
    • 不支持 IIFE 格式中的复杂全局变量映射
    • esbuild 的 Tree Shaking 不如 Rollup 精确(特别是对 side effects 的判断)
  3. DTS 生成仍为实验性dts: true 在复杂类型场景下可能产生不正确的声明文件
  4. CSS 支持有限:仅为实验性,不支持 PostCSS、CSS Modules 等高级功能
  5. 不支持 splitting: false:某些场景下无法精确控制 chunk 生成
  6. 无 Stub 模式:不像 unbuild/tsdown 支持生成代理文件用于 monorepo 开发
  7. 不支持 SWC:虽然 v8.5.0 曾尝试添加 SWC 支持,但整体集成有限

不适用场景

  • 大型应用打包:tsup 面向库打包,不适合 Webpack/Vite 的应用级打包场景
  • 需要复杂 CSS 管线的 UI 库:考虑 Vite Library Mode 或 Rslib
  • 需要极致 Tree Shaking 的库:Rollup/unbuild 的 Tree Shaking 更精确
  • 需要丰富插件生态的场景:esbuild 插件生态不如 Rollup 丰富
  • 对构建速度有极致要求的大型 Monorepo:考虑 tsdown(Rolldown/Rust)

迁移注意事项

如果考虑从 tsup 迁移到 tsdown:

# 自动迁移工具
npx tsdown-migrate
 
# Monorepo 批量迁移
npx tsdown-migrate 'packages/*'
 
# 预览迁移变更
npx tsdown-migrate --dry-run

关键配置映射:

tsup 配置tsdown 配置
entryPointsentry
publicDircopy
bundle: falseunbundle: true
externaldeps.neverBundle
noExternaldeps.alwaysBundle
esbuildPluginsplugins(需换为 unplugin/rolldown)
metafiledevtools: true

迁移后建议:

  1. 在 tsconfig 中启用 isolatedDeclarations: true
  2. 使用 are-the-types-wrong 验证类型输出
  3. 考虑发布主版本以避免微妙不兼容

学习资源

官方资源

教程与指南

社区资源

视频资源

2026 年现状

最新版本

  • 当前版本:v8.5.1(2025 年 11 月 12 日发布)
  • 发布频率:v8.x 系列在 2024-2025 年间发布了 20+ 个版本,更新节奏在后期明显放缓
  • 历史总版本:206+ 个 release

维护状态

⚠️ 项目不再活跃维护。 GitHub 仓库中已明确标注:

"This project is not actively maintained anymore. Please consider using tsdown instead."

这意味着:

  • 现有版本仍然可用且稳定
  • 不会再有重大功能更新
  • 关键安全修复可能不会及时跟进
  • 社区 PR 合并速度显著降低

发展趋势

2025-2026 年 TypeScript 库打包领域的关键趋势:

  1. Rust 化加速:esbuild(Go)正在被 Rolldown(Rust)取代,Vite 8 也将切换到 Rolldown
  2. tsdown 崛起:作为 tsup 的直接继任者,tsdown 增长迅速,被多位知名框架作者推荐
  3. ESM-first 成为默认:新工具默认 ESM 优先,CJS 作为兼容输出
  4. DTS 生成标准化isolatedDeclarations 成为 TypeScript 5.5+ 的标准方案
  5. 零配置成为标配:几乎所有新工具都提供零配置体验

社区活跃度

指标数值
GitHub Stars~11,300+
npm 周下载量~560 万(仍为同类最高)
累计 Issue 数1,300+
贡献者200+
最近代码提交趋于停滞

未来路线图

tsup 本身已无公开的 future roadmap。生态的未来方向是:

  • 短期(2026):tsup 仍是"安全选择",文档最多、社区最大、95% 的场景够用
  • 中期(2026-2027):tsdown 逐步接管,新项目和迁移项目首选 tsdown
  • 长期:随着 Vite 8 采用 Rolldown,整个生态向 Rust 打包器迁移,esbuild 时代逐步落幕

选型建议(2026 年)

情况建议
新项目,从零开始选择 tsdown
现有 tsup 项目,运行正常继续使用 tsup,计划迁移到 tsdown
需要 Rollup 插件生态选择 unbuildRollup
在 UnJS/Nuxt 生态中选择 unbuild
需要极致构建性能选择 tsdown
快速原型/教学tsup 仍可用,但建议直接用 tsdown