Subchapter 8.30
references/option-unbundle.mdMarkdown6 KBView on GitHub
Unbundle mode (also called “bundleless” or “transpile-only”) outputs files that mirror your source structure, rather than bundling everything into single files. Each source file is compiled individually with a one-to-one mapping.
tsdown --unbundleexport default defineConfig({
entry: ['src/**/*.ts', '!**/*.test.ts'],
unbundle: true,
})src/
├── index.ts
├── utils/
│ ├── helper.ts
│ └── format.ts
└── components/
└── button.tsConfig:
export default defineConfig({
entry: ['src/index.ts'],
unbundle: true,
})Output:
dist/
├── index.mjs
├── utils/
│ ├── helper.mjs
│ └── format.mjs
└── components/
└── button.mjsAll imported files are output individually, preserving structure.
Output:
dist/
└── index.mjs (all code bundled together)✅ Building monorepo packages with shared utilities ✅ Users need to import individual modules ✅ Want clear source-to-output mapping ✅ Library with many independent utilities ✅ Debugging requires tracing specific files ✅ Incremental builds for faster development
❌ Single entry point application ❌ Want to optimize bundle size ❌ Need aggressive tree shaking ❌ Creating IIFE/UMD bundles ❌ Deploying to browsers directly
export default defineConfig({
entry: ['src/**/*.ts', '!**/*.test.ts'],
format: ['esm', 'cjs'],
unbundle: true,
dts: true,
})Benefits:
Usage:
// Users can import specific utilities
import { helper } from 'my-lib/utils/helper'
import { Button } from 'my-lib/components/button'export default defineConfig({
entry: ['src/index.ts'],
format: ['esm'],
unbundle: true,
outDir: 'dist',
})export default defineConfig({
entry: ['src/**/*.ts'],
format: ['esm'],
unbundle: true,
minify: false,
treeshake: false,
dts: true,
})Pure TypeScript to JavaScript transformation.
export default defineConfig((options) => ({
entry: ['src/**/*.ts'],
unbundle: options.watch, // Unbundle in dev only
minify: !options.watch,
}))Fast rebuilds during development, optimized for production.
export default defineConfig({
entry: [
'src/**/*.ts',
'!**/*.test.ts',
'!**/*.spec.ts',
'!**/fixtures/**',
],
unbundle: true,
})export default defineConfig({
entry: {
index: 'src/index.ts',
cli: 'src/cli.ts',
},
unbundle: true,
})Both entry files and all imports preserved.
export default defineConfig({
entry: ['src/**/*.ts'],
unbundle: true,
outExtensions: () => ({ js: '.js' }),
})export default defineConfig({
entry: ['src/**/*.ts'],
unbundle: true,
outDir: 'lib',
})Output:
lib/
├── index.js
├── utils/
│ └── helper.js
└── components/
└── button.js{
"name": "my-library",
"type": "module",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": "./dist/index.js",
"./utils/*": "./dist/utils/*.js",
"./components/*": "./dist/components/*.js"
},
"files": ["dist"]
}Or use exports: true to auto-generate.
| Feature | Bundled | Unbundled |
|---|---|---|
| Output files | Few | Many |
| File size | Smaller | Larger |
| Build speed | Slower | Faster |
| Tree shaking | Build time | User’s build |
| Source mapping | Complex | Simple |
| Module imports | Entry only | Any module |
| Dev rebuilds | Slower | Faster |
Unbundle is typically faster:
Unbundle produces larger output:
# Enable unbundle
tsdown --unbundle
# With specific entry
tsdown src/**/*.ts --unbundle
# With other options
tsdown --unbundle --format esm --dts