tsup の使い方

Bundle your TypeScript library with no config, powered by esbuild

v8.5.1/週MITビルドツール
AI生成コンテンツ

この記事はAIによって生成されました。内容の正確性は保証されません。最新の情報は公式ドキュメントをご確認ください。

tsup の使い方完全ガイド — TypeScriptライブラリを設定なしでバンドル

一言でいうと

tsup は、esbuild をベースにした TypeScript ライブラリ向けのバンドルツールです。設定ファイルなし(ゼロコンフィグ)で .ts / .tsx ファイルを高速にバンドルし、ESM / CJS / IIFE 形式で出力できます。

⚠️ 重要な注意(2025年時点) tsup は公式にメンテナンス終了が宣言されています。新規プロジェクトでは後継の tsdown への移行が推奨されています。ただし、既存プロジェクトで広く使われており、動作自体に問題はないため、本記事では tsup v8.5.1 を基に解説します。


どんな時に使う?

  1. npm パッケージ(ライブラリ)の公開 — ESM と CJS の両方を同時に出力し、package.jsonexports フィールドに対応したビルドを簡単に構築できます。
  2. CLI ツールのバンドル — エントリポイントを指定するだけで、依存関係を解決した単一ファイルの CLI バイナリを生成できます。
  3. モノレポ内の共有パッケージのビルド — 設定が最小限で済むため、複数パッケージのビルドパイプラインを統一的に管理できます。

インストール

# npm
npm install tsup -D

# yarn
yarn add tsup --dev

# pnpm
pnpm add tsup -D

TypeScript がプロジェクトにインストールされていない場合は、併せてインストールしてください。

npm install typescript -D

基本的な使い方

最小構成でのバンドル

npx tsup src/index.ts

これだけで dist/index.js(CJS 形式)が生成されます。

package.json にスクリプトを追加

{
  "name": "my-library",
  "scripts": {
    "build": "tsup src/index.ts --format cjs,esm --dts",
    "dev": "tsup src/index.ts --format cjs,esm --dts --watch"
  }
}

設定ファイルを使う(推奨)

プロジェクトルートに tsup.config.ts を作成します。

// tsup.config.ts
import { defineConfig } from 'tsup'

export default defineConfig({
  entry: ['src/index.ts'],
  format: ['cjs', 'esm'],
  dts: true,
  splitting: true,
  sourcemap: true,
  clean: true,
})
npx tsup

設定ファイルがあれば、引数なしで tsup を実行するだけでビルドが走ります。

出力される package.json の設定例

{
  "name": "my-library",
  "version": "1.0.0",
  "main": "./dist/index.js",
  "module": "./dist/index.mjs",
  "types": "./dist/index.d.ts",
  "exports": {
    ".": {
      "import": "./dist/index.mjs",
      "require": "./dist/index.js",
      "types": "./dist/index.d.ts"
    }
  },
  "files": ["dist"]
}

よく使う API・オプション

1. format — 出力フォーマットの指定

CJS・ESM・IIFE の3形式をサポートしています。

import { defineConfig } from 'tsup'

export default defineConfig({
  entry: ['src/index.ts'],
  format: ['cjs', 'esm', 'iife'],
})
format出力拡張子用途
cjs.jsNode.js (CommonJS)
esm.mjsNode.js / ブラウザ (ES Modules)
iife.global.jsブラウザ <script> タグ

2. dts — TypeScript 型定義ファイルの生成

import { defineConfig } from 'tsup'

export default defineConfig({
  entry: ['src/index.ts'],
  format: ['esm'],
  dts: true, // .d.ts / .d.mts を自動生成
})

型定義の生成だけを別プロセスで行いたい場合は --dts-only フラグも使えます。

npx tsup src/index.ts --dts-only

3. entry — 複数エントリポイントとグロブ

import { defineConfig } from 'tsup'

export default defineConfig({
  // 配列で複数指定
  entry: ['src/index.ts', 'src/cli.ts'],

  // オブジェクト形式で出力名を制御
  // entry: {
  //   index: 'src/index.ts',
  //   cli: 'src/cli.ts',
  // },

  format: ['cjs', 'esm'],
})

グロブパターンも使用可能です。

export default defineConfig({
  entry: ['src/**/*.ts'],
  format: ['esm'],
})

4. external / noExternal — 依存関係のバンドル制御

デフォルトでは dependenciespeerDependencies に記載されたパッケージは外部モジュール扱い(バンドルしない)になります。

import { defineConfig } from 'tsup'

export default defineConfig({
  entry: ['src/index.ts'],
  format: ['esm'],
  // 明示的に外部化
  external: ['react', 'react-dom'],
  // 逆に、特定のパッケージを強制的にバンドルに含める
  noExternal: ['lodash-es'],
})

5. onSuccess — ビルド成功後のフック

ビルド完了後にコマンドを実行できます。開発時のサーバー再起動などに便利です。

import { defineConfig } from 'tsup'

export default defineConfig({
  entry: ['src/index.ts'],
  format: ['esm'],
  onSuccess: 'node dist/index.mjs',
  // async 関数も指定可能
  // onSuccess: async () => {
  //   console.log('Build succeeded!')
  // },
})

watch モードと組み合わせると、ファイル変更 → ビルド → 自動実行のサイクルが回ります。

npx tsup --watch

類似パッケージとの比較

特徴tsuptsdownunbuildrollup + pluginstsc (単体)
ベースエンジンesbuildrolldownrollup + esbuildrollupTypeScript compiler
ゼロコンフィグ
ビルド速度⚡ 非常に速い⚡ 非常に速い🔶 速い🔶 普通🐢 遅い
型定義生成要プラグイン✅(本業)
ESM + CJS 同時出力手動設定
Tree Shaking
メンテナンス状況⚠️ 終了宣言✅ 活発✅ 活発✅ 活発✅ 活発

新規プロジェクトでの推奨: tsup の後継である tsdown が最有力候補です。API が tsup と非常に似ているため、移行コストも低いです。


注意点・Tips

1. dts 生成は esbuild ではなく TypeScript コンパイラで行われる

バンドル自体は esbuild で高速に処理されますが、dts: true を指定した場合の型定義生成は TypeScript の API を使います。そのため、大規模プロジェクトでは型定義の生成がボトルネックになることがあります。

// 型定義の生成を並列実行にする(デフォルト動作)
export default defineConfig({
  dts: true, // バンドルと並列で .d.ts を生成
})

ビルド時間が問題になる場合は、tsc --emitDeclarationOnly を別ステップで実行する運用も検討してください。

2. target の指定を忘れない

esbuild のデフォルトターゲットは esnext です。古い Node.js バージョンをサポートする場合は明示的に指定しましょう。

export default defineConfig({
  entry: ['src/index.ts'],
  target: 'node18',
  format: ['cjs', 'esm'],
})

3. splitting は ESM 形式でのみ有効

コード分割(splitting: true)は ESM 出力でのみ動作します。CJS 形式では無視されます。

export default defineConfig({
  entry: ['src/index.ts', 'src/utils.ts'],
  format: ['esm'],
  splitting: true, // 共通コードを別チャンクに分離
})

4. clean オプションで古い出力を削除

ビルド前に dist ディレクトリを自動クリーンアップできます。CI/CD 環境では必ず有効にしておくのがおすすめです。

export default defineConfig({
  clean: true,
})

5. 環境変数の注入

export default defineConfig({
  define: {
    'process.env.NODE_ENV': JSON.stringify('production'),
  },
  env: {
    API_URL: 'https://api.example.com',
  },
})

env で指定した値は process.env.API_URL としてコード内で参照できます。

6. tsup.config.ts で条件分岐

defineConfig にはコールバック形式もあり、ビルドオプション(--watch かどうかなど)に応じて設定を切り替えられます。

import { defineConfig } from 'tsup'

export default defineConfig((options) => ({
  entry: ['src/index.ts'],
  format: ['cjs', 'esm'],
  dts: true,
  sourcemap: true,
  minify: !options.watch, // watch モードではミニファイしない
  clean: true,
}))

まとめ

tsup は「TypeScript ライブラリのバンドルをとにかく手軽に始めたい」というニーズに対する最適解として、長く支持されてきたツールです。esbuild による高速ビルド、ESM/CJS の同時出力、型定義の自動生成といった機能がゼロコンフィグで手に入る点は、今なお大きな魅力です。

ただし、公式にメンテナンス終了が宣言されているため、新規プロジェクトでは後継の tsdown を第一候補として検討してください。既存プロジェクトについても、移行ガイドを参照しながら段階的に移行を進めることをおすすめします。