TSDX

Migration Guide

This guide helps you migrate from the original TSDX (v0.x) to the modern TSDX 2.0.

What's Changed

TSDX 2.0 is a complete rewrite that replaces the original toolchain with modern, high-performance alternatives:

Old (v0.x)New (v2.0)Why
Rollup + BabelbuncheeZero-config, SWC-powered, faster
JestvitestVite-native, faster, Jest-compatible
ESLintoxlint50-100x faster, Rust-powered
Prettieroxfmt35x faster, Rust-powered
yarn/npmbunFaster installs and execution
Node 10+Node 20+LTS only

Quick Migration

1. Install Bun

curl -fsSL https://bun.sh/install | bash
powershell -c "irm bun.sh/install.ps1 | iex"

2. Update package.json Scripts

Replace your scripts:

{
  "scripts": {
    "dev": "tsdx dev",
    "build": "tsdx build",
    "test": "tsdx test",
    "lint": "tsdx lint",
    "format": "tsdx format",
    "typecheck": "tsdx typecheck",
    "prepublishOnly": "bun run build"
  }
}

3. Update Dependencies

# Remove old dependencies
bun remove tsdx rollup @rollup/plugin-* babel-* @babel/* jest ts-jest eslint @typescript-eslint/* prettier husky lint-staged

# Add new tsdx
bun add -D tsdx typescript

4. Replace Jest with Vitest

Create vitest.config.ts:

import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    globals: true,
    environment: 'node', // or 'jsdom' for React/DOM testing
  },
});

5. Remove Old Config Files

Delete these files (they're no longer needed):

rm -f tsdx.config.js
rm -f jest.config.js
rm -f .babelrc babel.config.js babel.config.json
rm -f .eslintrc .eslintrc.js .eslintrc.json .eslintignore
rm -f .prettierrc .prettierrc.js .prettierrc.json .prettierignore
rm -f rollup.config.js
rm -f yarn.lock package-lock.json

6. Update tsconfig.json

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "lib": ["ES2022", "DOM"],
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "declaration": true,
    "declarationMap": true,
    "outDir": "./dist",
    "rootDir": "./src",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true
  },
  "include": ["src"],
  "exclude": ["node_modules", "dist"]
}

7. Update package.json Exports

{
  "type": "module",
  "main": "./dist/index.cjs",
  "module": "./dist/index.js",
  "types": "./dist/index.d.ts",
  "exports": {
    ".": {
      "import": {
        "types": "./dist/index.d.ts",
        "default": "./dist/index.js"
      },
      "require": {
        "types": "./dist/index.d.cts",
        "default": "./dist/index.cjs"
      }
    },
    "./package.json": "./package.json"
  },
  "files": ["dist", "src"],
  "engines": {
    "node": ">=20"
  }
}

8. Install and Test

bun install
bun run test
bun run build
bun run lint

Jest to Vitest Migration

Most Jest tests work with Vitest without changes. Here's a quick reference:

JestVitest
jest.fn()vi.fn()
jest.mock()vi.mock()
jest.spyOn()vi.spyOn()
jest.useFakeTimers()vi.useFakeTimers()
beforeAll/afterAllSame
beforeEach/afterEachSame
describe/it/testSame
expect()Same

If using globals (globals: true in vitest.config.ts), you don't need imports. Otherwise:

import { describe, it, expect, vi } from 'vitest';

Breaking Changes

Removed Features

  1. Storybook template - Use Storybook CLI directly
  2. Custom Rollup config (tsdx.config.js) - Use bunchee config or raw rollup if needed
  3. UMD builds - Modern tooling focuses on ESM and CJS
  4. Error extraction - This feature has been removed
  5. Node.js < 20 - Only Node.js 20+ (LTS) is supported

Changed Behavior

  1. Build output - Slightly different but compatible
  2. Watch mode - Now uses bunchee's watch
  3. Test runner - Vitest instead of Jest (mostly compatible API)
  4. Default branch - Uses main instead of master in templates

Compatibility

Your Library Consumers

No changes needed! The build output format is compatible:

  • ESM and CommonJS dual publish
  • TypeScript declarations
  • Same export patterns

Command Changes

TaskOld CommandNew Command
Create projectnpx tsdx create mylibbunx tsdx create mylib
Developmentyarn startbun run dev
Buildyarn buildbun run build
Testyarn testbun run test
Lintyarn lintbun run lint
Formatyarn prettier --write .bun run format

Troubleshooting

"bun: command not found"

Install bun:

curl -fsSL https://bun.sh/install | bash

Tests fail with "vi is not defined"

Add vitest imports or enable globals:

// Option 1: Add imports
import { describe, it, expect, vi } from 'vitest';

// Option 2: Enable globals in vitest.config.ts
export default defineConfig({
  test: { globals: true },
});

TypeScript errors with moduleResolution

Update tsconfig.json:

{
  "compilerOptions": {
    "moduleResolution": "bundler"
  }
}

ESM/CJS interop issues

Ensure your package.json has:

{
  "type": "module"
}

Getting Help

On this page