一、引言
如果你曾用TypeScript编写过一个npm包,一定经历过这样的纠结:用tsc只能输出JS,无法打包;用Rollup配置复杂,光是让TypeScript、CommonJS和ES Module和平共处就要折腾半天;用Webpack又太重,杀鸡用牛刀。
2025年,如果你去问一个开源库作者“TypeScript库用什么打包”,十有八九会得到一个答案——tsup。这个由EGOIST开发的打包工具,基于esbuild构建,以“零配置、极速构建、多格式输出”著称,周下载量超过270万。从shadcn/ui到React-Redux,从Turborepo示例项目到无数个人开源库,tsup已成为TypeScript库打包的事实标准。
二、tsup是什么
tsup是一个基于esbuild的TypeScript库打包工具,官方定位是“最简单、最快的TypeScript库打包方式”。
2.1 它解决了什么问题?
写一个TypeScript npm包,通常面临三个核心需求:
- TS转译:把
.ts/.tsx源码转成JavaScript - 双模式兼容:同时输出ESM(ES Module)和CJS(CommonJS)两种格式,让用户无论用
import还是require都能使用 - 类型声明生成:输出
.d.ts文件,提供TypeScript类型支持
传统方案需要组合使用tsc、Rollup、rollup-plugin-dts等多个工具,配置繁琐且容易出错。tsup的价值就在于——一个工具、一条命令、一次搞定。
三、核心特性
3.1 零配置,开箱即用
tsup最核心的设计理念是“no config”——提供合理的默认值,让大多数TypeScript库项目无需配置文件即可工作。
最简单的用法只有一条命令:
tsup src/index.ts这条命令自动完成:TypeScript/JavaScript打包、输出到./dist目录、自动排除node_modules依赖。
3.2 极速构建
tsup底层基于esbuild——一个用Go语言编写的打包器,构建速度比传统工具(Webpack、Rollup)快10-100倍。
速度差异在大型项目中尤为明显。一个中等规模的TypeScript库,tsc编译可能需要几秒,而tsup通常在毫秒级完成。这种速度优势让开发时的“修改→构建→测试”循环几乎无感。
3.3 多格式输出
tsup可以在一次构建中同时生成多种模块格式:
| 格式 | 扩展名 | 适用场景 |
|---|---|---|
| cjs | .js/.cjs | Node.js CommonJS |
| esm | .mjs/.js | 现代ES Module环境 |
| iife | .global.js | 浏览器全局变量 |
这意味着你只需要一次配置,就能同时兼容所有主流使用场景。
3.4 智能依赖外置
tsup会自动将package.json中的dependencies和peerDependencies标记为外部依赖,避免将node_modules打包进库中——这对Node.js库来说通常是正确做法。
3.5 双引擎策略
tsup采用了一个精妙的设计:用esbuild打包JavaScript,用Rollup打包类型声明。
- esbuild负责JS:极速构建、原生TS支持、内置压缩和Tree-shaking
- Rollup负责.d.ts:将分散的类型声明文件合并为单一入口,处理复杂的类型依赖关系
这种“各取所长”的策略,让tsup在速度和正确性之间取得了最佳平衡。
3.6 TypeScript类型声明生成
通过--dts参数,tsup可以自动生成合并后的.d.ts类型声明文件:
tsup src/index.ts--dts输出产物中会包含index.d.ts,用户安装你的包后即可获得完整的TypeScript类型支持。
四、实际应用场景
4.1 主要适用场景
tsup最擅长的场景是TypeScript npm包的构建,具体包括:
- 纯JS/TS工具库:如lodash、dayjs这类通用工具函数库
- React/Vue组件库:需要同时输出ESM和CJS,并保留类型声明
- CLI工具:支持Shebang,自动添加
#!/usr/bin/env node - Monorepo中的共享包:与Turborepo等工具配合,实现高效的包间构建
4.2 shadcn/ui:开源组件库的标杆案例
shadcn/ui是当前最流行的React组件库之一,其构建工具正是tsup。通过tsup,shadcn/ui实现了:
- 同时输出ESM和CJS两种格式
- 完整的TypeScript类型支持
- 极快的构建速度,保障了频繁发布的效率
4.3 React-Redux:大型项目的构建优化
React-Redux作为Redux官方的React绑定库,其构建配置直接影响了数百万项目的开发体验。React-Redux团队选择tsup作为构建工具,实现了:
- 环境分离打包:通过
NODE_ENV区分开发和生产环境,生成不同产物 - 多格式输出:同时输出CJS和ESM格式
- 按需加载优化:利用tsup的Tree-shaking能力
4.4 个人组件库与设计系统
无数个人开发者和团队使用tsup构建自己的组件库和设计系统。一个典型的配置会:
- 将
react、antd等运行时依赖标记为peerDependencies并通过--external排除 - 同时生成ESM、CJS和
.d.ts类型声明 - 利用watch模式实现开发时的实时构建
4.5 Monorepo中的共享包
在Turborepo等Monorepo方案中,tsup常被用于构建各个共享包。配合--watch模式,可以实现“修改共享包→自动重新构建→上层应用热更新”的流畅开发体验。
五、开发实践指南
5.1 安装
在项目根目录执行:
npminstalltsup-D# 或yarnaddtsup--dev# 或pnpmaddtsup-D5.2 基础配置
创建tsup.config.ts配置文件:
import{defineConfig}from'tsup'exportdefaultdefineConfig({entry:['src/index.ts'],// 入口文件format:['esm','cjs'],// 同时输出ESM和CJSdts:true,// 生成类型声明文件sourcemap:true,// 生成sourcemapclean:true,// 构建前清空dist目录minify:false,// 开发环境不压缩splitting:false,// 库打包不需要代码分割target:'es2020',// 转译目标})5.3 在package.json中配置脚本
{"scripts":{"build":"tsup","dev":"tsup --watch","prepublishOnly":"npm run build"}}5.4 React组件库的典型配置
对于React组件库,需要将React等运行时依赖排除:
import{defineConfig}from'tsup'exportdefaultdefineConfig({entry:['src/index.ts'],format:['esm','cjs'],dts:true,external:['react','react-dom'],sourcemap:true,clean:true,})5.5 CLI工具的配置
如果构建的是命令行工具,需要开启shebang选项:
exportdefaultdefineConfig({entry:['src/cli.ts'],format:['cjs'],shebang:true,// 自动添加 #!/usr/bin/env nodedts:true,})5.6 实践建议
- 类型检查与构建分离:tsup默认不做类型检查(为了速度),建议在CI或pre-commit中单独运行
tsc --noEmit。 - 善用watch模式:开发时使用
tsup --watch,修改源码后自动重新构建。 - 按需使用minify:库代码通常不需要压缩(交给应用层做),保持可读性更有利于调试。
- 注意CSS支持:tsup的CSS支持仍处于实验阶段,复杂样式方案建议配合其他工具。
六、与其他工具的对比
| 工具 | 优势 | 适用场景 |
|---|---|---|
| tsup | 零配置、极速、双格式输出、类型声明 | 大多数TypeScript库 |
| tsdown | Rolldown引擎、更快、更低内存 | 新项目、Vite生态 |
| Rollup | 最强Tree-shaking、插件生态丰富 | 复杂构建需求 |
| unbuild | Rollup底层、Nuxt生态 | Nuxt/UnJS项目 |
| esbuild | 最底层的极速引擎 | 需要完全自定义的场景 |
tsup是目前最主流、最成熟的选择,周下载量达270万。tsdown作为新兴工具值得关注,但对现有tsup项目无需急于迁移。
七、总结
tsup之所以能成为TypeScript库打包的“默认答案”,核心在于它精准地解决了库作者的三个核心痛点:
- 配置复杂→ 零配置,开箱即用
- 构建太慢→ 基于esbuild,毫秒级构建
- 格式兼容→ 一次构建,同时输出ESM、CJS、类型声明
它不试图做所有事,而是把TypeScript库打包这件事做到极致。无论你是在开发一个开源工具库、一个React组件库,还是一个CLI工具,tsup都能让你把精力放在写代码上,而不是配置构建工具上。
正如社区所言:“tsup wraps esbuild with library defaults, while raw esbuild leaves declaration files and package output conventions to you.”——tsup就是那个帮你搞定所有“约定俗成”的打包工具。