feat: Complete fleet — 94 skills across 10+ domains

Pulled ALL skills from 15 source repositories:
- anthropics/skills: 16 (docs, design, MCP, testing)
- obra/superpowers: 14 (TDD, debugging, agents, planning)
- coreyhaines31/marketingskills: 25 (marketing, CRO, SEO, growth)
- better-auth/skills: 5 (auth patterns)
- vercel-labs/agent-skills: 5 (React, design, Vercel)
- antfu/skills: 16 (Vue, Vite, Vitest, pnpm, Turborepo)
- Plus 13 individual skills from various repos

Mosaic Stack is not limited to coding — the Orchestrator and
subagents serve coding, business, design, marketing, writing,
logistics, analysis, and more.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jason Woltje
2026-02-16 16:27:42 -06:00
parent 861b28b965
commit f5792c40be
1262 changed files with 212048 additions and 61 deletions

22
skills/tsdown/LICENSE.md Normal file
View File

@@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2025-present VoidZero Inc. & Contributors
Copyright (c) 2024 Kevin Deng (https://github.com/sxzz)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

69
skills/tsdown/README.md Normal file
View File

@@ -0,0 +1,69 @@
# tsdown Skills for Claude Code
Agent skills that help Claude Code understand and work with [tsdown](https://tsdown.dev), the elegant library bundler.
## Installation
```bash
npx skills add rolldown/tsdown
```
This will add the tsdown skill to your Claude Code configuration.
## What's Included
The tsdown skill provides Claude Code with knowledge about:
- **Core Concepts** - What tsdown is, why use it, key features
- **Configuration** - Config file formats, options, multiple configs, workspace support
- **Build Options** - Entry points, output formats, type declarations, targets
- **Dependency Handling** - External/inline dependencies, auto-externalization
- **Output Enhancement** - Shims, CJS defaults, package exports
- **Framework Support** - React, Vue, Solid, Svelte integration
- **Advanced Features** - Plugins, hooks, programmatic API, Rolldown options
- **CLI Commands** - All CLI options and usage patterns
- **Migration** - Migrating from tsup to tsdown
## Usage
Once installed, Claude Code will automatically use tsdown knowledge when:
- Building TypeScript/JavaScript libraries
- Configuring bundlers for library projects
- Setting up type declaration generation
- Working with multi-format builds (ESM, CJS, IIFE, UMD)
- Migrating from tsup
- Building framework component libraries
### Example Prompts
```
Set up tsdown to build my TypeScript library with ESM and CJS formats
```
```
Configure tsdown to generate type declarations and bundle for browsers
```
```
Add React support to my tsdown config with Fast Refresh
```
```
Help me migrate from tsup to tsdown
```
```
Set up a monorepo build with tsdown workspace support
```
## Documentation
- [tsdown Documentation](https://tsdown.dev)
- [GitHub Repository](https://github.com/rolldown/tsdown)
- [Rolldown](https://rolldown.rs)
- [Migration Guide](https://tsdown.dev/guide/migrate-from-tsup)
## License
MIT

344
skills/tsdown/SKILL.md Normal file
View File

@@ -0,0 +1,344 @@
---
name: tsdown
description: Bundle TypeScript and JavaScript libraries with blazing-fast speed powered by Rolldown. Use when building libraries, generating type declarations, bundling for multiple formats, or migrating from tsup.
---
# tsdown - The Elegant Library Bundler
Blazing-fast bundler for TypeScript/JavaScript libraries powered by Rolldown and Oxc.
## When to Use
- Building TypeScript/JavaScript libraries for npm
- Generating TypeScript declaration files (.d.ts)
- Bundling for multiple formats (ESM, CJS, IIFE, UMD)
- Optimizing bundles with tree shaking and minification
- Migrating from tsup with minimal changes
- Building React, Vue, Solid, or Svelte component libraries
## Quick Start
```bash
# Install
pnpm add -D tsdown
# Basic usage
npx tsdown
# With config file
npx tsdown --config tsdown.config.ts
# Watch mode
npx tsdown --watch
# Migrate from tsup
npx tsdown-migrate
```
## Basic Configuration
```ts
import { defineConfig } from 'tsdown'
export default defineConfig({
entry: ['./src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
clean: true,
})
```
## Core References
| Topic | Description | Reference |
|-------|-------------|-----------|
| Getting Started | Installation, first bundle, CLI basics | [guide-getting-started](references/guide-getting-started.md) |
| Configuration File | Config file formats, multiple configs, workspace | [option-config-file](references/option-config-file.md) |
| CLI Reference | All CLI commands and options | [reference-cli](references/reference-cli.md) |
| Migrate from tsup | Migration guide and compatibility notes | [guide-migrate-from-tsup](references/guide-migrate-from-tsup.md) |
| Plugins | Rolldown, Rollup, Unplugin support | [advanced-plugins](references/advanced-plugins.md) |
| Hooks | Lifecycle hooks for custom logic | [advanced-hooks](references/advanced-hooks.md) |
| Programmatic API | Build from Node.js scripts | [advanced-programmatic](references/advanced-programmatic.md) |
| Rolldown Options | Pass options directly to Rolldown | [advanced-rolldown-options](references/advanced-rolldown-options.md) |
| CI Environment | CI detection, `'ci-only'` / `'local-only'` values | [advanced-ci](references/advanced-ci.md) |
## Build Options
| Option | Usage | Reference |
|--------|-------|-----------|
| Entry points | `entry: ['src/*.ts', '!**/*.test.ts']` | [option-entry](references/option-entry.md) |
| Output formats | `format: ['esm', 'cjs', 'iife', 'umd']` | [option-output-format](references/option-output-format.md) |
| Output directory | `outDir: 'dist'`, `outExtensions` | [option-output-directory](references/option-output-directory.md) |
| Type declarations | `dts: true`, `dts: { sourcemap, compilerOptions, vue }` | [option-dts](references/option-dts.md) |
| Target environment | `target: 'es2020'`, `target: 'esnext'` | [option-target](references/option-target.md) |
| Platform | `platform: 'node'`, `platform: 'browser'` | [option-platform](references/option-platform.md) |
| Tree shaking | `treeshake: true`, custom options | [option-tree-shaking](references/option-tree-shaking.md) |
| Minification | `minify: true`, `minify: 'dce-only'` | [option-minification](references/option-minification.md) |
| Source maps | `sourcemap: true`, `'inline'`, `'hidden'` | [option-sourcemap](references/option-sourcemap.md) |
| Watch mode | `watch: true`, watch options | [option-watch-mode](references/option-watch-mode.md) |
| Cleaning | `clean: true`, clean patterns | [option-cleaning](references/option-cleaning.md) |
| Log level | `logLevel: 'silent'`, `failOnWarn: 'ci-only'` | [option-log-level](references/option-log-level.md) |
## Dependency Handling
| Feature | Usage | Reference |
|---------|-------|-----------|
| External deps | `external: ['react', /^@myorg\//]` | [option-dependencies](references/option-dependencies.md) |
| Inline deps | `noExternal: ['dep-to-bundle']` | [option-dependencies](references/option-dependencies.md) |
| Auto external | Automatic peer/dependency externalization | [option-dependencies](references/option-dependencies.md) |
## Output Enhancement
| Feature | Usage | Reference |
|---------|-------|-----------|
| Shims | `shims: true` - Add ESM/CJS compatibility | [option-shims](references/option-shims.md) |
| CJS default | `cjsDefault: true` (default) / `false` | [option-cjs-default](references/option-cjs-default.md) |
| Package exports | `exports: true` - Auto-generate exports field | [option-package-exports](references/option-package-exports.md) |
| CSS handling | **[experimental]** Still in development | [option-css](references/option-css.md) |
| Unbundle mode | `unbundle: true` - Preserve directory structure | [option-unbundle](references/option-unbundle.md) |
| Package validation | `publint: true`, `attw: true` - Validate package | [option-lint](references/option-lint.md) |
## Framework & Runtime Support
| Framework | Guide | Reference |
|-----------|-------|-----------|
| React | JSX transform, Fast Refresh | [recipe-react](references/recipe-react.md) |
| Vue | SFC support, JSX | [recipe-vue](references/recipe-vue.md) |
| WASM | WebAssembly modules via `rolldown-plugin-wasm` | [recipe-wasm](references/recipe-wasm.md) |
## Common Patterns
### Basic Library Bundle
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
clean: true,
})
```
### Multiple Entry Points
```ts
export default defineConfig({
entry: {
index: 'src/index.ts',
utils: 'src/utils.ts',
cli: 'src/cli.ts',
},
format: ['esm', 'cjs'],
dts: true,
})
```
### Browser Library (IIFE/UMD)
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['iife'],
globalName: 'MyLib',
platform: 'browser',
minify: true,
})
```
### React Component Library
```ts
export default defineConfig({
entry: ['src/index.tsx'],
format: ['esm', 'cjs'],
dts: true,
external: ['react', 'react-dom'],
plugins: [
// React Fast Refresh support
],
})
```
### Preserve Directory Structure
```ts
export default defineConfig({
entry: ['src/**/*.ts', '!**/*.test.ts'],
unbundle: true, // Preserve file structure
format: ['esm'],
dts: true,
})
```
### CI-Aware Configuration
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
failOnWarn: 'ci-only',
publint: 'ci-only',
attw: 'ci-only',
})
```
### WASM Support
```ts
import { wasm } from 'rolldown-plugin-wasm'
import { defineConfig } from 'tsdown'
export default defineConfig({
entry: ['src/index.ts'],
plugins: [wasm()],
})
```
### Advanced with Hooks
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
hooks: {
'build:before': async (context) => {
console.log('Building...')
},
'build:done': async (context) => {
console.log('Build complete!')
},
},
})
```
## Configuration Features
### Multiple Configs
Export an array for multiple build configurations:
```ts
export default defineConfig([
{
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
},
{
entry: ['src/cli.ts'],
format: ['esm'],
platform: 'node',
},
])
```
### Conditional Config
Use functions for dynamic configuration:
```ts
export default defineConfig((options) => {
const isDev = options.watch
return {
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
minify: !isDev,
sourcemap: isDev,
}
})
```
### Workspace/Monorepo
Use glob patterns to build multiple packages:
```ts
export default defineConfig({
workspace: 'packages/*',
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
})
```
## CLI Quick Reference
```bash
# Basic commands
tsdown # Build once
tsdown --watch # Watch mode
tsdown --config custom.ts # Custom config
npx tsdown-migrate # Migrate from tsup
# Output options
tsdown --format esm,cjs # Multiple formats
tsdown --outDir lib # Custom output directory
tsdown --minify # Enable minification
tsdown --dts # Generate declarations
# Entry options
tsdown src/index.ts # Single entry
tsdown src/*.ts # Glob patterns
tsdown src/a.ts src/b.ts # Multiple entries
# Development
tsdown --watch # Watch mode
tsdown --sourcemap # Generate source maps
tsdown --clean # Clean output directory
```
## Best Practices
1. **Always generate type declarations** for TypeScript libraries:
```ts
{ dts: true }
```
2. **Externalize dependencies** to avoid bundling unnecessary code:
```ts
{ external: [/^react/, /^@myorg\//] }
```
3. **Use tree shaking** for optimal bundle size:
```ts
{ treeshake: true }
```
4. **Enable minification** for production builds:
```ts
{ minify: true }
```
5. **Add shims** for better ESM/CJS compatibility:
```ts
{ shims: true } // Adds __dirname, __filename, etc.
```
6. **Auto-generate package.json exports**:
```ts
{ exports: true } // Creates proper exports field
```
7. **Use watch mode** during development:
```bash
tsdown --watch
```
8. **Preserve structure** for utilities with many files:
```ts
{ unbundle: true } // Keep directory structure
```
9. **Validate packages** in CI before publishing:
```ts
{ publint: 'ci-only', attw: 'ci-only' }
```
## Resources
- Documentation: https://tsdown.dev
- GitHub: https://github.com/rolldown/tsdown
- Rolldown: https://rolldown.rs
- Migration Guide: https://tsdown.dev/guide/migrate-from-tsup

5
skills/tsdown/SYNC.md Normal file
View File

@@ -0,0 +1,5 @@
# Sync Info
- **Source:** `vendor/tsdown/skills/tsdown`
- **Git SHA:** `76b612274f6bf4efb9f1b9285ea2aad56556df67`
- **Synced:** 2026-01-31

View File

@@ -0,0 +1,139 @@
# tsdown Skill References
This directory contains detailed reference documentation for the tsdown skill.
## Created Files (31 total)
### Core Guides (2)
-`guide-getting-started.md` - Installation, first bundle, CLI basics
-`guide-migrate-from-tsup.md` - Migration guide from tsup
### Configuration Options (20)
-`option-config-file.md` - Config file formats, loaders, workspace
-`option-entry.md` - Entry point configuration with globs
-`option-output-format.md` - Output formats (ESM, CJS, IIFE, UMD)
-`option-output-directory.md` - Output directory and extensions
-`option-dts.md` - TypeScript declaration generation
-`option-target.md` - Target environment (ES2020, ESNext, etc.)
-`option-platform.md` - Platform (node, browser, neutral)
-`option-dependencies.md` - External and inline dependencies
-`option-sourcemap.md` - Source map generation
-`option-minification.md` - Minification (`boolean | 'dce-only' | MinifyOptions`)
-`option-tree-shaking.md` - Tree shaking configuration
-`option-cleaning.md` - Output directory cleaning
-`option-watch-mode.md` - Watch mode configuration
-`option-shims.md` - ESM/CJS compatibility shims
-`option-package-exports.md` - Auto-generate package.json exports
-`option-css.md` - CSS handling (experimental, stub only)
-`option-unbundle.md` - Preserve directory structure
-`option-cjs-default.md` - CommonJS default export handling
-`option-log-level.md` - Logging configuration
-`option-lint.md` - Package validation (publint & attw)
### Advanced Topics (5)
-`advanced-plugins.md` - Rolldown, Rollup, Unplugin support
-`advanced-hooks.md` - Lifecycle hooks system
-`advanced-programmatic.md` - Node.js API usage
-`advanced-rolldown-options.md` - Pass options to Rolldown
-`advanced-ci.md` - CI environment detection and CI-aware options
### Framework Recipes (3)
-`recipe-react.md` - React library setup with JSX
-`recipe-vue.md` - Vue library setup with SFC
-`recipe-wasm.md` - WASM module support
### Reference (1)
-`reference-cli.md` - Complete CLI command reference
## Coverage Status
**Created:** 31 files (97% complete)
**Remaining:** 3 files (low priority, not referenced from SKILL.md)
### Remaining Files (Lower Priority)
These files can be added as needed:
1. **`guide-introduction.md`** - Covered in main SKILL.md
2. **`guide-faq.md`** - FAQ (stub mode, etc.)
3. **`advanced-benchmark.md`** - Performance data
## Current Skill Features
The tsdown skill now includes comprehensive coverage of:
### ✅ Core Functionality
- Getting started and installation
- Entry points and glob patterns
- Output formats (ESM, CJS, IIFE, UMD)
- TypeScript declarations
- Configuration file setup
- CLI reference
### ✅ Build Options
- Target environment configuration
- Platform selection
- Dependency management
- Source maps
- Minification
- Tree shaking
- Output cleaning
- Watch mode
### ✅ Advanced Features
- Plugins (Rolldown, Rollup, Unplugin)
- Lifecycle hooks
- ESM/CJS shims
- Package exports generation
- Package validation (publint, attw)
- Programmatic API (Node.js)
- Output directory customization
- CSS handling and modules
- Unbundle mode
- CI environment detection and CI-aware options
### ✅ Framework & Runtime Support
- React with JSX/TSX
- React Compiler integration
- Vue with SFC support
- Vue type generation (vue-tsc)
- WASM module bundling (rolldown-plugin-wasm)
### ✅ Migration
- Complete migration guide from tsup
- Compatibility notes
## Usage
The skill is now ready for use with comprehensive coverage of core features. Additional files can be added incrementally as needed.
## File Naming Convention
Files are prefixed by category:
- `guide-*` - Getting started guides and tutorials
- `option-*` - Configuration options
- `advanced-*` - Advanced topics (plugins, hooks, programmatic API)
- `recipe-*` - Framework-specific recipes
- `reference-*` - CLI and API reference
## Creating New Reference Files
When creating new reference files:
1. **Read source documentation** from `/docs` directory
2. **Simplify for AI consumption** - concise, actionable content
3. **Include code examples** - practical, copy-paste ready
4. **Add cross-references** - link to related options
5. **Follow naming convention** - use appropriate prefix
6. **Keep it focused** - one topic per file
## Updating Existing Files
When documentation changes:
1. Check git diff: `git diff <sha>..HEAD -- docs/`
2. Update affected reference files
3. Update SKILL.md if needed
4. Update GENERATION.md with new SHA
See `skills/GENERATION.md` for detailed update instructions.

View File

@@ -0,0 +1,89 @@
# CI Environment Support
Automatically detect CI environments and toggle features based on local vs CI builds.
## Overview
tsdown uses the [`is-in-ci`](https://www.npmjs.com/package/is-in-ci) package to detect CI environments. This covers GitHub Actions, GitLab CI, Jenkins, CircleCI, Travis CI, and more.
## CI-Aware Values
Several options accept CI-aware string values:
| Value | Behavior |
|-------|----------|
| `true` | Always enabled |
| `false` | Always disabled |
| `'ci-only'` | Enabled only in CI, disabled locally |
| `'local-only'` | Enabled only locally, disabled in CI |
## Supported Options
These options accept CI-aware values:
- `dts` - TypeScript declaration file generation
- `publint` - Package lint validation
- `attw` - "Are the types wrong" validation
- `report` - Bundle size reporting
- `exports` - Auto-generate `package.json` exports
- `unused` - Unused dependency check
- `devtools` - DevTools integration
- `failOnWarn` - Fail on warnings (defaults to `'ci-only'`)
## Usage
### String Form
```ts
export default defineConfig({
dts: 'local-only', // Skip DTS in CI for faster builds
publint: 'ci-only', // Only run publint in CI
failOnWarn: 'ci-only', // Fail on warnings in CI only (default)
})
```
### Object Form
When an option takes a configuration object, set `enabled` to a CI-aware value:
```ts
export default defineConfig({
publint: {
enabled: 'ci-only',
level: 'error',
},
attw: {
enabled: 'ci-only',
profile: 'node16',
},
})
```
### Config Function
The config function receives a `ci` boolean in its context:
```ts
export default defineConfig((_, { ci }) => ({
minify: ci,
sourcemap: !ci,
}))
```
## Typical CI Configuration
```ts
export default defineConfig({
entry: 'src/index.ts',
format: ['esm', 'cjs'],
dts: true,
failOnWarn: 'ci-only',
publint: 'ci-only',
attw: 'ci-only',
})
```
## Related Options
- [Package Validation](option-lint.md) - publint and attw configuration
- [Log Level](option-log-level.md) - `failOnWarn` option details

View File

@@ -0,0 +1,363 @@
# Lifecycle Hooks
Extend the build process with lifecycle hooks.
## Overview
Hooks provide a way to inject custom logic at specific stages of the build lifecycle. Inspired by [unbuild](https://github.com/unjs/unbuild).
**Recommendation:** Use [plugins](advanced-plugins.md) for most extensions. Use hooks for simple custom tasks or Rolldown plugin injection.
## Usage Patterns
### Object Syntax
```ts
export default defineConfig({
entry: ['src/index.ts'],
hooks: {
'build:prepare': async (context) => {
console.log('Build starting...')
},
'build:done': async (context) => {
console.log('Build complete!')
},
},
})
```
### Function Syntax
```ts
export default defineConfig({
entry: ['src/index.ts'],
hooks(hooks) {
hooks.hook('build:prepare', () => {
console.log('Preparing build...')
})
hooks.hook('build:before', (context) => {
console.log(`Building format: ${context.format}`)
})
},
})
```
## Available Hooks
### `build:prepare`
Called before the build process starts.
**When:** Once per build session
**Context:**
```ts
{
options: ResolvedConfig,
hooks: Hookable
}
```
**Use cases:**
- Setup tasks
- Validation
- Environment preparation
**Example:**
```ts
hooks: {
'build:prepare': async (context) => {
console.log('Starting build for:', context.options.entry)
await cleanOldFiles()
},
}
```
### `build:before`
Called before each Rolldown build.
**When:** Once per format (ESM, CJS, etc.)
**Context:**
```ts
{
options: ResolvedConfig,
buildOptions: BuildOptions,
hooks: Hookable
}
```
**Use cases:**
- Modify build options per format
- Inject plugins dynamically
- Format-specific setup
**Example:**
```ts
hooks: {
'build:before': async (context) => {
console.log(`Building ${context.buildOptions.format} format...`)
// Add format-specific plugin
if (context.buildOptions.format === 'iife') {
context.buildOptions.plugins.push(browserPlugin())
}
},
}
```
### `build:done`
Called after the build completes.
**When:** Once per build session
**Context:**
```ts
{
options: ResolvedConfig,
chunks: RolldownChunk[],
hooks: Hookable
}
```
**Use cases:**
- Post-processing
- Asset copying
- Notifications
- Deployment
**Example:**
```ts
hooks: {
'build:done': async (context) => {
console.log(`Built ${context.chunks.length} chunks`)
// Copy additional files
await copyAssets()
// Send notification
notifyBuildComplete()
},
}
```
## Common Patterns
### Build Notifications
```ts
export default defineConfig({
hooks: {
'build:prepare': () => {
console.log('🚀 Starting build...')
},
'build:done': (context) => {
const size = context.chunks.reduce((sum, c) => sum + c.code.length, 0)
console.log(`✅ Build complete! Total size: ${size} bytes`)
},
},
})
```
### Conditional Plugin Injection
```ts
export default defineConfig({
hooks(hooks) {
hooks.hook('build:before', (context) => {
// Add minification only for production
if (process.env.NODE_ENV === 'production') {
context.buildOptions.plugins.push(minifyPlugin())
}
})
},
})
```
### Custom File Copy
```ts
import { copyFile } from 'fs/promises'
export default defineConfig({
hooks: {
'build:done': async (context) => {
// Copy README to dist
await copyFile('README.md', `${context.options.outDir}/README.md`)
},
},
})
```
### Build Metrics
```ts
export default defineConfig({
hooks: {
'build:prepare': (context) => {
context.startTime = Date.now()
},
'build:done': (context) => {
const duration = Date.now() - context.startTime
console.log(`Build took ${duration}ms`)
// Log chunk sizes
context.chunks.forEach((chunk) => {
console.log(`${chunk.fileName}: ${chunk.code.length} bytes`)
})
},
},
})
```
### Format-Specific Logic
```ts
export default defineConfig({
format: ['esm', 'cjs', 'iife'],
hooks: {
'build:before': (context) => {
const format = context.buildOptions.format
if (format === 'iife') {
// Browser-specific setup
context.buildOptions.globalName = 'MyLib'
} else if (format === 'cjs') {
// Node-specific setup
context.buildOptions.platform = 'node'
}
},
},
})
```
### Deployment Hook
```ts
export default defineConfig({
hooks: {
'build:done': async (context) => {
if (process.env.DEPLOY === 'true') {
console.log('Deploying to CDN...')
await deployToCDN(context.options.outDir)
}
},
},
})
```
## Advanced Usage
### Multiple Hooks
```ts
export default defineConfig({
hooks(hooks) {
// Register multiple hooks
hooks.hook('build:prepare', setupEnvironment)
hooks.hook('build:prepare', validateConfig)
hooks.hook('build:before', injectPlugins)
hooks.hook('build:before', logFormat)
hooks.hook('build:done', generateManifest)
hooks.hook('build:done', notifyComplete)
},
})
```
### Async Hooks
```ts
export default defineConfig({
hooks: {
'build:prepare': async (context) => {
await fetchRemoteConfig()
await initializeDatabase()
},
'build:done': async (context) => {
await uploadToS3(context.chunks)
await invalidateCDN()
},
},
})
```
### Error Handling
```ts
export default defineConfig({
hooks: {
'build:done': async (context) => {
try {
await riskyOperation()
} catch (error) {
console.error('Hook failed:', error)
// Don't throw - allow build to complete
}
},
},
})
```
## Hookable API
tsdown uses [hookable](https://github.com/unjs/hookable) for hooks. Additional methods:
```ts
export default defineConfig({
hooks(hooks) {
// Register hook
hooks.hook('build:done', handler)
// Register hook once
hooks.hookOnce('build:prepare', handler)
// Remove hook
hooks.removeHook('build:done', handler)
// Clear all hooks for event
hooks.removeHooks('build:done')
// Call hooks manually
await hooks.callHook('build:done', context)
},
})
```
## Tips
1. **Use plugins** for most extensions
2. **Hooks for simple tasks** like notifications or file copying
3. **Async hooks supported** for I/O operations
4. **Don't throw errors** unless you want to fail the build
5. **Context is mutable** in `build:before` for advanced use cases
6. **Multiple hooks allowed** for the same event
## Troubleshooting
### Hook Not Called
- Verify hook name is correct
- Check hook is registered in config
- Ensure async hooks are awaited
### Build Fails in Hook
- Add try/catch for error handling
- Don't throw unless intentional
- Log errors for debugging
### Context Undefined
- Check which hook you're using
- Verify context properties available for that hook
## Related
- [Plugins](advanced-plugins.md) - Plugin system
- [Rolldown Options](advanced-rolldown-options.md) - Build options
- [Watch Mode](option-watch-mode.md) - Development workflow

View File

@@ -0,0 +1,381 @@
# Plugins
Extend tsdown with plugins from multiple ecosystems.
## Overview
tsdown, built on Rolldown, supports plugins from multiple ecosystems to extend and customize the bundling process.
## Supported Ecosystems
### 1. Rolldown Plugins
Native plugins designed for Rolldown:
```ts
import RolldownPlugin from 'rolldown-plugin-something'
export default defineConfig({
plugins: [RolldownPlugin()],
})
```
**Compatibility:** ✅ Full support
### 2. Unplugin
Universal plugins that work across bundlers:
```ts
import UnpluginPlugin from 'unplugin-something'
export default defineConfig({
plugins: [UnpluginPlugin.rolldown()],
})
```
**Compatibility:** ✅ Most unplugin-* plugins work
**Examples:**
- `unplugin-vue-components`
- `unplugin-auto-import`
- `unplugin-icons`
### 3. Rollup Plugins
Most Rollup plugins work with tsdown:
```ts
import RollupPlugin from '@rollup/plugin-something'
export default defineConfig({
plugins: [RollupPlugin()],
})
```
**Compatibility:** ✅ High compatibility
**Type Issues:** May cause TypeScript errors - use type casting:
```ts
import RollupPlugin from 'rollup-plugin-something'
export default defineConfig({
plugins: [
// @ts-expect-error Rollup plugin type mismatch
RollupPlugin(),
// Or cast to any
RollupPlugin() as any,
],
})
```
### 4. Vite Plugins
Some Vite plugins may work:
```ts
import VitePlugin from 'vite-plugin-something'
export default defineConfig({
plugins: [
// @ts-expect-error Vite plugin type mismatch
VitePlugin(),
],
})
```
**Compatibility:** ⚠️ Limited - only if not using Vite-specific APIs
**Note:** Improved support planned for future releases.
## Usage
### Basic Plugin Usage
```ts
import { defineConfig } from 'tsdown'
import SomePlugin from 'some-plugin'
export default defineConfig({
entry: ['src/index.ts'],
plugins: [SomePlugin()],
})
```
### Multiple Plugins
```ts
import PluginA from 'plugin-a'
import PluginB from 'plugin-b'
import PluginC from 'plugin-c'
export default defineConfig({
entry: ['src/index.ts'],
plugins: [
PluginA(),
PluginB({ option: true }),
PluginC(),
],
})
```
### Conditional Plugins
```ts
export default defineConfig((options) => ({
entry: ['src/index.ts'],
plugins: [
SomePlugin(),
options.watch && DevPlugin(),
!options.watch && ProdPlugin(),
].filter(Boolean),
}))
```
## Common Plugin Patterns
### JSON Import
```ts
import json from '@rollup/plugin-json'
export default defineConfig({
plugins: [json()],
})
```
### Node Resolve
```ts
import { nodeResolve } from '@rollup/plugin-node-resolve'
export default defineConfig({
plugins: [nodeResolve()],
})
```
### CommonJS
```ts
import commonjs from '@rollup/plugin-commonjs'
export default defineConfig({
plugins: [commonjs()],
})
```
### Replace
```ts
import replace from '@rollup/plugin-replace'
export default defineConfig({
plugins: [
replace({
'process.env.NODE_ENV': JSON.stringify('production'),
__VERSION__: JSON.stringify('1.0.0'),
}),
],
})
```
### Auto Import
```ts
import AutoImport from 'unplugin-auto-import/rolldown'
export default defineConfig({
plugins: [
AutoImport({
imports: ['vue', 'vue-router'],
dts: 'src/auto-imports.d.ts',
}),
],
})
```
### Vue Components
```ts
import Components from 'unplugin-vue-components/rolldown'
export default defineConfig({
plugins: [
Components({
dts: 'src/components.d.ts',
}),
],
})
```
## Framework-Specific Plugins
### React
```ts
import react from '@vitejs/plugin-react'
export default defineConfig({
entry: ['src/index.tsx'],
plugins: [
// @ts-expect-error Vite plugin
react(),
],
})
```
### Vue
```ts
import vue from '@vitejs/plugin-vue'
export default defineConfig({
entry: ['src/index.ts'],
plugins: [
// @ts-expect-error Vite plugin
vue(),
],
})
```
### Solid
```ts
import solid from 'vite-plugin-solid'
export default defineConfig({
entry: ['src/index.tsx'],
plugins: [
// @ts-expect-error Vite plugin
solid(),
],
})
```
### Svelte
```ts
import { svelte } from '@sveltejs/vite-plugin-svelte'
export default defineConfig({
entry: ['src/index.ts'],
plugins: [
// @ts-expect-error Vite plugin
svelte(),
],
})
```
## Writing Custom Plugins
Follow Rolldown's plugin development guide:
### Basic Plugin Structure
```ts
import type { Plugin } from 'rolldown'
function myPlugin(): Plugin {
return {
name: 'my-plugin',
// Transform hook
transform(code, id) {
if (id.endsWith('.custom')) {
return {
code: transformCode(code),
map: null,
}
}
},
// Other hooks...
}
}
```
### Using Custom Plugin
```ts
import { myPlugin } from './my-plugin'
export default defineConfig({
plugins: [myPlugin()],
})
```
## Plugin Configuration
### Plugin-Specific Options
Refer to each plugin's documentation for configuration options.
### Plugin Order
Plugins run in the order they're defined:
```ts
export default defineConfig({
plugins: [
PluginA(), // Runs first
PluginB(), // Runs second
PluginC(), // Runs last
],
})
```
## Troubleshooting
### Type Errors with Rollup/Vite Plugins
Use type casting:
```ts
plugins: [
// Option 1: @ts-expect-error
// @ts-expect-error Plugin type mismatch
SomePlugin(),
// Option 2: as any
SomePlugin() as any,
]
```
### Plugin Not Working
1. **Check compatibility** - Verify plugin supports your bundler
2. **Read documentation** - Follow plugin's setup instructions
3. **Check plugin order** - Some plugins depend on execution order
4. **Enable debug mode** - Use `--debug` flag
### Vite Plugin Fails
Vite plugins may rely on Vite-specific APIs:
1. **Find Rollup equivalent** - Look for Rollup version of plugin
2. **Use Unplugin version** - Check for `unplugin-*` alternative
3. **Wait for support** - Vite plugin support improving
## Resources
- [Rolldown Plugin Development](https://rolldown.rs/guide/plugin-development)
- [Unplugin Documentation](https://unplugin.unjs.io/)
- [Rollup Plugins](https://github.com/rollup/plugins)
- [Vite Plugins](https://vitejs.dev/plugins/)
## Tips
1. **Prefer Rolldown plugins** for best compatibility
2. **Use Unplugin** for cross-bundler support
3. **Cast types** for Rollup/Vite plugins
4. **Test thoroughly** when using cross-ecosystem plugins
5. **Check plugin docs** for specific configuration
6. **Write custom plugins** for unique needs
## Related
- [Hooks](advanced-hooks.md) - Lifecycle hooks
- [Rolldown Options](advanced-rolldown-options.md) - Advanced Rolldown config
- [React Recipe](recipe-react.md) - React setup with plugins
- [Vue Recipe](recipe-vue.md) - Vue setup with plugins

View File

@@ -0,0 +1,376 @@
# Programmatic Usage
Use tsdown from JavaScript/TypeScript code.
## Overview
tsdown can be imported and used programmatically in your Node.js scripts, custom build tools, or automation workflows.
## Basic Usage
### Simple Build
```ts
import { build } from 'tsdown'
await build({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
})
```
### With Options
```ts
import { build } from 'tsdown'
await build({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
outDir: 'dist',
dts: true,
minify: true,
sourcemap: true,
clean: true,
})
```
## API Reference
### build()
Main function to run a build.
```ts
import { build } from 'tsdown'
await build(options)
```
**Parameters:**
- `options` - Build configuration object (same as config file)
**Returns:**
- `Promise<void>` - Resolves when build completes
**Throws:**
- Build errors if compilation fails
## Configuration Object
All config file options are available:
```ts
import { build, defineConfig } from 'tsdown'
const config = defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
minify: true,
sourcemap: true,
external: ['react', 'react-dom'],
plugins: [/* plugins */],
hooks: {
'build:done': async () => {
console.log('Build complete!')
},
},
})
await build(config)
```
See [Config Reference](option-config-file.md) for all options.
## Common Patterns
### Custom Build Script
```ts
// scripts/build.ts
import { build } from 'tsdown'
async function main() {
console.log('Building library...')
await build({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
clean: true,
})
console.log('Build complete!')
}
main().catch(console.error)
```
Run with:
```bash
tsx scripts/build.ts
```
### Multiple Builds
```ts
import { build } from 'tsdown'
// Build main library
await build({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
outDir: 'dist',
dts: true,
})
// Build CLI tool
await build({
entry: ['src/cli.ts'],
format: ['esm'],
outDir: 'dist/bin',
platform: 'node',
shims: true,
})
```
### Conditional Build
```ts
import { build } from 'tsdown'
const isDev = process.env.NODE_ENV === 'development'
await build({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
minify: !isDev,
sourcemap: isDev,
clean: !isDev,
})
```
### With Error Handling
```ts
import { build } from 'tsdown'
try {
await build({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
})
console.log('✅ Build successful')
} catch (error) {
console.error('❌ Build failed:', error)
process.exit(1)
}
```
### Automated Workflow
```ts
import { build } from 'tsdown'
import { execSync } from 'child_process'
async function release() {
// Clean
console.log('Cleaning...')
execSync('rm -rf dist')
// Build
console.log('Building...')
await build({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
minify: true,
})
// Test
console.log('Testing...')
execSync('npm test')
// Publish
console.log('Publishing...')
execSync('npm publish')
}
release().catch(console.error)
```
### Build with Post-Processing
```ts
import { build } from 'tsdown'
import { copyFileSync } from 'fs'
await build({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
hooks: {
'build:done': async () => {
// Copy additional files
copyFileSync('README.md', 'dist/README.md')
copyFileSync('LICENSE', 'dist/LICENSE')
console.log('Copied additional files')
},
},
})
```
## Watch Mode
Unfortunately, watch mode is not directly exposed in the programmatic API. Use the CLI for watch mode:
```ts
// Use CLI for watch mode
import { spawn } from 'child_process'
spawn('tsdown', ['--watch'], {
stdio: 'inherit',
shell: true,
})
```
## Integration Examples
### With Task Runner
```ts
// gulpfile.js
import { build } from 'tsdown'
import gulp from 'gulp'
gulp.task('build', async () => {
await build({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
})
})
gulp.task('watch', () => {
return gulp.watch('src/**/*.ts', gulp.series('build'))
})
```
### With Custom CLI
```ts
// scripts/cli.ts
import { build } from 'tsdown'
import { Command } from 'commander'
const program = new Command()
program
.command('build')
.option('--prod', 'Production build')
.action(async (options) => {
await build({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
minify: options.prod,
sourcemap: !options.prod,
})
})
program.parse()
```
### With CI/CD
```ts
// .github/scripts/build.ts
import { build } from 'tsdown'
const isCI = process.env.CI === 'true'
await build({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
minify: isCI,
clean: true,
})
// Upload to artifact storage
if (isCI) {
// Upload dist/ to S3, etc.
}
```
## TypeScript Support
```ts
// scripts/build.ts
import { build, type UserConfig } from 'tsdown'
const config: UserConfig = {
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
}
await build(config)
```
## Tips
1. **Use TypeScript** for type safety
2. **Handle errors** properly
3. **Use hooks** for custom logic
4. **Log progress** for visibility
5. **Use CLI for watch** mode
6. **Exit on error** in scripts
## Troubleshooting
### Import Errors
Ensure tsdown is installed:
```bash
pnpm add -D tsdown
```
### Type Errors
Import types:
```ts
import type { UserConfig } from 'tsdown'
```
### Build Fails Silently
Add error handling:
```ts
try {
await build(config)
} catch (error) {
console.error(error)
process.exit(1)
}
```
### Options Not Working
Check spelling and types:
```ts
// ✅ Correct
{ format: ['esm', 'cjs'] }
// ❌ Wrong
{ formats: ['esm', 'cjs'] }
```
## Related
- [Config File](option-config-file.md) - Configuration options
- [Hooks](advanced-hooks.md) - Lifecycle hooks
- [CLI](reference-cli.md) - Command-line interface
- [Plugins](advanced-plugins.md) - Plugin system

View File

@@ -0,0 +1,117 @@
# Customizing Rolldown Options
Pass options directly to the underlying Rolldown bundler.
## Overview
tsdown uses [Rolldown](https://rolldown.rs) as its core bundling engine. You can override Rolldown's input and output options directly for fine-grained control.
**Warning:** You should be familiar with Rolldown's behavior before overriding options. Refer to the [Rolldown Config Options](https://rolldown.rs/options/input) documentation.
## Input Options
### Using an Object
```ts
export default defineConfig({
inputOptions: {
cwd: './custom-directory',
},
})
```
### Using a Function
Dynamically modify options based on the output format:
```ts
export default defineConfig({
inputOptions(inputOptions, format) {
inputOptions.cwd = './custom-directory'
return inputOptions
},
})
```
## Output Options
### Using an Object
```ts
export default defineConfig({
outputOptions: {
legalComments: 'inline',
},
})
```
### Using a Function
```ts
export default defineConfig({
outputOptions(outputOptions, format) {
if (format === 'esm') {
outputOptions.legalComments = 'inline'
}
return outputOptions
},
})
```
## Common Use Cases
### Preserve Legal Comments
```ts
export default defineConfig({
entry: ['src/index.ts'],
outputOptions: {
legalComments: 'inline',
},
})
```
### Custom Working Directory
```ts
export default defineConfig({
entry: ['src/index.ts'],
inputOptions: {
cwd: './packages/my-lib',
},
})
```
### Format-Specific Options
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
outputOptions(outputOptions, format) {
if (format === 'esm') {
outputOptions.legalComments = 'inline'
}
return outputOptions
},
})
```
## When to Use
- When tsdown doesn't expose a specific Rolldown option
- For format-specific Rolldown customizations
- For advanced bundling scenarios
## Tips
1. **Read Rolldown docs** before overriding options
2. **Use functions** for format-specific customization
3. **Test thoroughly** when overriding defaults
4. **Prefer tsdown options** when available (e.g., use `minify` instead of setting it via `outputOptions`)
## Related
- [Plugins](advanced-plugins.md) - Plugin system
- [Hooks](advanced-hooks.md) - Lifecycle hooks
- [Config File](option-config-file.md) - Configuration options

View File

@@ -0,0 +1,178 @@
# Getting Started
Quick guide to installing and using tsdown for the first time.
## Installation
Install tsdown as a development dependency:
```bash
pnpm add -D tsdown
# Optionally install TypeScript if not using isolatedDeclarations
pnpm add -D typescript
```
**Requirements:**
- Node.js 20.19 or higher
- Experimental support for Deno and Bun
## Quick Start Templates
Use `create-tsdown` CLI for instant setup:
```bash
pnpm create tsdown@latest
```
Provides templates for:
- Pure TypeScript libraries
- React component libraries
- Vue component libraries
- Ready-to-use configurations
## First Bundle
### 1. Create Source Files
```ts
// src/index.ts
import { hello } from './hello.ts'
hello()
// src/hello.ts
export function hello() {
console.log('Hello tsdown!')
}
```
### 2. Create Config File
```ts
// tsdown.config.ts
import { defineConfig } from 'tsdown'
export default defineConfig({
entry: ['./src/index.ts'],
})
```
### 3. Run Build
```bash
./node_modules/.bin/tsdown
```
Output: `dist/index.mjs`
### 4. Test Output
```bash
node dist/index.mjs
# Output: Hello tsdown!
```
## Add to npm Scripts
```json
{
"scripts": {
"build": "tsdown"
}
}
```
Run with:
```bash
pnpm build
```
## CLI Commands
```bash
# Check version
tsdown --version
# View help
tsdown --help
# Build with watch mode
tsdown --watch
# Build with specific format
tsdown --format esm,cjs
# Generate type declarations
tsdown --dts
```
## Basic Configurations
### TypeScript Library (ESM + CJS)
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
clean: true,
})
```
### Browser Library (IIFE)
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['iife'],
globalName: 'MyLib',
platform: 'browser',
minify: true,
})
```
### Multiple Entry Points
```ts
export default defineConfig({
entry: {
index: 'src/index.ts',
utils: 'src/utils.ts',
cli: 'src/cli.ts',
},
format: ['esm', 'cjs'],
dts: true,
})
```
## Using Plugins
Add Rolldown, Rollup, or Unplugin plugins:
```ts
import SomePlugin from 'some-plugin'
export default defineConfig({
entry: ['src/index.ts'],
plugins: [SomePlugin()],
})
```
## Watch Mode
Enable automatic rebuilds on file changes:
```bash
tsdown --watch
# or
tsdown -w
```
## Next Steps
- Configure [entry points](option-entry.md) with glob patterns
- Set up [multiple output formats](option-output-format.md)
- Enable [type declaration generation](option-dts.md)
- Explore [plugins](advanced-plugins.md) for extended functionality
- Read [migration guide](guide-migrate-from-tsup.md) if coming from tsup

View File

@@ -0,0 +1,189 @@
# Migrate from tsup
Migration guide for switching from tsup to tsdown.
## Overview
tsdown is built on Rolldown (Rust-based) vs tsup's esbuild, providing faster and more powerful bundling while maintaining compatibility.
## Automatic Migration
### Single Package
```bash
npx tsdown-migrate
```
### Monorepo
```bash
# Using glob patterns
npx tsdown-migrate packages/*
# Multiple directories
npx tsdown-migrate packages/foo packages/bar
```
### Migration Options
- `[...dirs]` - Directories to migrate (supports globs)
- `--dry-run` or `-d` - Preview changes without modifying files
**Important:** Commit your changes before running migration.
## Key Differences
### Default Values
| Option | tsup | tsdown |
|--------|------|--------|
| `format` | `['cjs']` | `['esm']` |
| `clean` | `false` | `true` |
| `dts` | `false` | Auto-enabled if `types`/`typings` in package.json |
| `target` | Manual | Auto-read from `engines.node` in package.json |
### New Features in tsdown
#### Node Protocol Control
```ts
export default defineConfig({
nodeProtocol: true, // Add node: prefix (fs → node:fs)
nodeProtocol: 'strip', // Remove node: prefix (node:fs → fs)
nodeProtocol: false, // Keep as-is (default)
})
```
#### Better Workspace Support
```ts
export default defineConfig({
workspace: 'packages/*', // Build all packages
})
```
## Migration Checklist
1. **Backup your code** - Commit all changes
2. **Run migration tool** - `npx tsdown-migrate`
3. **Review changes** - Check modified config files
4. **Update scripts** - Change `tsup` to `tsdown` in package.json
5. **Test build** - Run `pnpm build` to verify
6. **Adjust config** - Fine-tune based on your needs
## Common Migration Patterns
### Basic Library
**Before (tsup):**
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['cjs', 'esm'],
dts: true,
})
```
**After (tsdown):**
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'], // ESM now default
dts: true,
clean: true, // Now enabled by default
})
```
### With Custom Target
**Before (tsup):**
```ts
export default defineConfig({
entry: ['src/index.ts'],
target: 'es2020',
})
```
**After (tsdown):**
```ts
export default defineConfig({
entry: ['src/index.ts'],
// target auto-reads from package.json engines.node
// Or override explicitly:
target: 'es2020',
})
```
### CLI Scripts
**Before (package.json):**
```json
{
"scripts": {
"build": "tsup",
"dev": "tsup --watch"
}
}
```
**After (package.json):**
```json
{
"scripts": {
"build": "tsdown",
"dev": "tsdown --watch"
}
}
```
## Feature Compatibility
### Supported tsup Features
Most tsup features are supported:
- ✅ Multiple entry points
- ✅ Multiple formats (ESM, CJS, IIFE, UMD)
- ✅ TypeScript declarations
- ✅ Source maps
- ✅ Minification
- ✅ Watch mode
- ✅ External dependencies
- ✅ Tree shaking
- ✅ Shims
- ✅ Plugins (Rollup compatible)
### Missing Features
Some tsup features are not yet available. Check [GitHub issues](https://github.com/rolldown/tsdown/issues) for status and request features.
## Troubleshooting
### Build Fails After Migration
1. **Check Node.js version** - Requires Node.js 20.19+
2. **Install TypeScript** - Required for DTS generation
3. **Review config changes** - Ensure format and options are correct
4. **Check dependencies** - Verify all dependencies are installed
### Different Output
- **Format order** - tsdown defaults to ESM first
- **Clean behavior** - tsdown cleans outDir by default
- **Target** - tsdown auto-detects from package.json
### Performance Issues
tsdown should be faster than tsup. If not:
1. Enable `isolatedDeclarations` for faster DTS generation
2. Check for large dependencies being bundled
3. Use `skipNodeModulesBundle` if needed
## Getting Help
- [GitHub Issues](https://github.com/rolldown/tsdown/issues) - Report bugs or request features
- [Documentation](https://tsdown.dev) - Full documentation
- [Migration Tool](https://github.com/rolldown/tsdown/tree/main/packages/tsdown-migrate) - Source code
## Acknowledgements
tsdown is heavily inspired by tsup and incorporates parts of its codebase. Thanks to [@egoist](https://github.com/egoist) and the tsup community.

View File

@@ -0,0 +1,98 @@
# CJS Default Export
Control how default exports are handled in CommonJS output.
## Overview
The `cjsDefault` option improves compatibility when generating CommonJS modules. When enabled (default), modules with only a single default export use `module.exports = ...` instead of `exports.default = ...`.
## Type
```ts
cjsDefault?: boolean // default: true
```
## Basic Usage
### Enabled (Default)
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['cjs'],
cjsDefault: true, // default behavior
})
```
### Disabled
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['cjs'],
cjsDefault: false,
})
```
## How It Works
### With `cjsDefault: true` (Default)
When your module has **only a single default export**, tsdown transforms:
**Source:**
```ts
// src/index.ts
export default function greet() {
console.log('Hello, world!')
}
```
**Generated CJS:**
```js
// dist/index.cjs
function greet() {
console.log('Hello, world!')
}
module.exports = greet
```
**Generated Declaration:**
```ts
// dist/index.d.cts
declare function greet(): void
export = greet
```
This allows consumers to use `const greet = require('your-module')` directly.
### With `cjsDefault: false`
The default export stays as `exports.default`:
```js
// dist/index.cjs
function greet() {
console.log('Hello, world!')
}
exports.default = greet
```
Consumers need `require('your-module').default`.
## When to Disable
- When your module has both default and named exports
- When you need consistent `exports.default` behavior
- When consumers always use ESM imports
## Tips
1. **Leave enabled** for most libraries (default `true`)
2. **Disable** if you have both default and named exports and need consistent behavior
3. **Test CJS consumers** to verify compatibility
## Related Options
- [Output Format](option-output-format.md) - Module formats
- [Shims](option-shims.md) - ESM/CJS compatibility

View File

@@ -0,0 +1,275 @@
# Output Directory Cleaning
Control how the output directory is cleaned before builds.
## Overview
By default, tsdown **cleans the output directory** before each build to remove stale files from previous builds.
## Basic Usage
### CLI
```bash
# Clean enabled (default)
tsdown
# Disable cleaning
tsdown --no-clean
```
### Config File
```ts
export default defineConfig({
entry: ['src/index.ts'],
clean: true, // Default
})
```
## Behavior
### With Cleaning (Default)
Before each build:
1. All files in `outDir` are removed
2. Fresh build starts with empty directory
3. Only current build outputs remain
**Benefits:**
- No stale files
- Predictable output
- Clean slate each build
### Without Cleaning
Build outputs are added to existing files:
```ts
export default defineConfig({
clean: false,
})
```
**Use when:**
- Multiple builds to same directory
- Incremental builds
- Preserving other files
- Watch mode (faster rebuilds)
## Common Patterns
### Production Build
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
clean: true, // Ensure clean output
minify: true,
})
```
### Development Mode
```ts
export default defineConfig((options) => ({
entry: ['src/index.ts'],
clean: !options.watch, // Don't clean in watch mode
sourcemap: options.watch,
}))
```
### Multiple Builds
```ts
export default defineConfig([
{
entry: ['src/index.ts'],
outDir: 'dist',
clean: true, // Clean once
},
{
entry: ['src/cli.ts'],
outDir: 'dist',
clean: false, // Don't clean, add to same dir
},
])
```
### Monorepo Package
```ts
export default defineConfig({
workspace: 'packages/*',
entry: ['src/index.ts'],
clean: true, // Clean each package's dist
})
```
### Preserve Static Files
```ts
export default defineConfig({
entry: ['src/index.ts'],
clean: false, // Keep manually added files
outDir: 'dist',
})
// Manually copy files first
// Then run tsdown --no-clean
```
## Clean Patterns
### Selective Cleaning
```ts
import { rmSync } from 'fs'
export default defineConfig({
clean: false, // Disable auto clean
hooks: {
'build:prepare': () => {
// Custom cleaning logic
rmSync('dist/*.js', { force: true })
// Keep other files
},
},
})
```
### Clean Specific Directories
```ts
export default defineConfig({
clean: false,
hooks: {
'build:prepare': async () => {
const { rm } = await import('fs/promises')
// Only clean specific subdirectories
await rm('dist/esm', { recursive: true, force: true })
await rm('dist/cjs', { recursive: true, force: true })
// Keep dist/types
},
},
})
```
## Watch Mode Behavior
In watch mode, cleaning behavior is important:
### Clean on First Build Only
```ts
export default defineConfig((options) => ({
entry: ['src/index.ts'],
watch: options.watch,
clean: !options.watch, // Only clean initial build
}))
```
**Result:**
- First build: Clean
- Subsequent rebuilds: Incremental
### Always Clean
```ts
export default defineConfig({
watch: true,
clean: true, // Clean every rebuild
})
```
**Trade-off:** Slower rebuilds, but always fresh output.
## Tips
1. **Leave enabled** for production builds
2. **Disable in watch mode** for faster rebuilds
3. **Use multiple configs** carefully with cleaning
4. **Custom clean logic** via hooks if needed
5. **Be cautious** - cleaning removes ALL files in outDir
6. **Test cleaning** - ensure no important files are lost
## Troubleshooting
### Important Files Deleted
- Don't put non-build files in outDir
- Use separate directory for static files
- Disable cleaning and manage manually
### Stale Files in Output
- Enable cleaning: `clean: true`
- Or manually remove before build
### Slow Rebuilds in Watch
- Disable cleaning in watch mode
- Use incremental builds
## CLI Examples
```bash
# Default (clean enabled)
tsdown
# Disable cleaning
tsdown --no-clean
# Watch mode without cleaning
tsdown --watch --no-clean
# Multiple formats with cleaning
tsdown --format esm,cjs --clean
```
## Examples
### Safe Production Build
```bash
# Clean before build
rm -rf dist
tsdown --clean
```
### Incremental Development
```ts
export default defineConfig({
entry: ['src/index.ts'],
watch: true,
clean: false, // Faster rebuilds
sourcemap: true,
})
```
### Multi-Stage Build
```ts
// Stage 1: Clean and build main
export default defineConfig([
{
entry: ['src/index.ts'],
outDir: 'dist',
clean: true,
},
{
entry: ['src/utils.ts'],
outDir: 'dist',
clean: false, // Add to same directory
},
])
```
## Related Options
- [Output Directory](option-output-directory.md) - Configure outDir
- [Watch Mode](option-watch-mode.md) - Development workflow
- [Hooks](advanced-hooks.md) - Custom clean logic
- [Entry](option-entry.md) - Entry points

View File

@@ -0,0 +1,281 @@
# Configuration File
Centralize and manage build settings with a configuration file.
## Overview
tsdown searches for config files automatically in the current directory and parent directories.
## Supported File Names
tsdown looks for these files (in order):
- `tsdown.config.ts`
- `tsdown.config.mts`
- `tsdown.config.cts`
- `tsdown.config.js`
- `tsdown.config.mjs`
- `tsdown.config.cjs`
- `tsdown.config.json`
- `tsdown.config`
- `package.json` (in `tsdown` field)
## Basic Configuration
### TypeScript Config
```ts
// tsdown.config.ts
import { defineConfig } from 'tsdown'
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
clean: true,
})
```
### JavaScript Config
```js
// tsdown.config.js
export default {
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
}
```
### JSON Config
```json
// tsdown.config.json
{
"entry": ["src/index.ts"],
"format": ["esm", "cjs"],
"dts": true
}
```
### Package.json Config
```json
// package.json
{
"name": "my-library",
"tsdown": {
"entry": ["src/index.ts"],
"format": ["esm", "cjs"],
"dts": true
}
}
```
## Multiple Configurations
Build multiple outputs with different settings:
```ts
export default defineConfig([
{
entry: 'src/index.ts',
format: ['esm', 'cjs'],
platform: 'node',
dts: true,
},
{
entry: 'src/browser.ts',
format: ['iife'],
platform: 'browser',
globalName: 'MyLib',
minify: true,
},
])
```
Each configuration runs as a separate build.
## Dynamic Configuration
Use a function for conditional config:
```ts
export default defineConfig((options) => {
const isDev = options.watch
return {
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
minify: !isDev,
sourcemap: isDev,
clean: !isDev,
}
})
```
Available options:
- `watch` - Whether watch mode is enabled
- Other CLI flags passed to config
## Config Loaders
Control how TypeScript config files are loaded:
### Auto Loader (Default)
Uses native TypeScript support if available, otherwise falls back to `unrun`:
```bash
tsdown # Uses auto loader
```
### Native Loader
Uses runtime's native TypeScript support (Node.js 23+, Bun, Deno):
```bash
tsdown --config-loader native
```
### Unrun Loader
Uses [unrun](https://gugustinette.github.io/unrun/) library for loading:
```bash
tsdown --config-loader unrun
```
**Tip:** Use `unrun` loader if you need to load TypeScript configs without file extensions in Node.js.
## Custom Config Path
Specify a custom config file location:
```bash
tsdown --config ./configs/build.config.ts
# or
tsdown -c custom-config.ts
```
## Disable Config File
Ignore config files and use CLI options only:
```bash
tsdown --no-config src/index.ts --format esm
```
## Extend Vite/Vitest Config (Experimental)
Reuse existing Vite or Vitest configurations:
```bash
# Extend vite.config.*
tsdown --from-vite
# Extend vitest.config.*
tsdown --from-vite vitest
```
**Note:** Only specific options like `resolve` and `plugins` are reused. Test thoroughly as this feature is experimental.
## Workspace / Monorepo
Build multiple packages with a single config:
```ts
export default defineConfig({
workspace: 'packages/*',
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
})
```
Each package directory matching the glob pattern will be built with the same configuration.
## Common Patterns
### Library with Multiple Builds
```ts
export default defineConfig([
// Node.js build
{
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
platform: 'node',
dts: true,
},
// Browser build
{
entry: ['src/browser.ts'],
format: ['iife'],
platform: 'browser',
globalName: 'MyLib',
},
])
```
### Development vs Production
```ts
export default defineConfig((options) => ({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
minify: !options.watch,
sourcemap: options.watch ? true : false,
clean: !options.watch,
}))
```
### Monorepo Root Config
```ts
// Root tsdown.config.ts
export default defineConfig({
workspace: 'packages/*',
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
clean: true,
// Shared config for all packages
})
```
### Per-Package Override
```ts
// packages/special/tsdown.config.ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm'], // Override: only ESM
platform: 'browser', // Override: browser only
})
```
## Config Precedence
When multiple configs exist:
1. CLI options (highest priority)
2. Config file specified with `--config`
3. Auto-discovered config files
4. Package.json `tsdown` field
5. Default values
## Tips
1. **Use TypeScript config** for type checking and autocomplete
2. **Use defineConfig** helper for better DX
3. **Export arrays** for multiple build configurations
4. **Use functions** for dynamic/conditional configs
5. **Keep configs simple** - prefer convention over configuration
6. **Use workspace** for monorepo builds
7. **Test experimental features** thoroughly before production use
## Related Options
- [Entry](option-entry.md) - Configure entry points
- [Output Format](option-output-format.md) - Output formats
- [Watch Mode](option-watch-mode.md) - Watch mode configuration

View File

@@ -0,0 +1,7 @@
# CSS Support
**Status: Experimental — still in active development.**
CSS handling in tsdown is not yet stable. The API and capabilities may change significantly in future releases.
Avoid relying on CSS-related options in production builds until the feature is marked as stable.

View File

@@ -0,0 +1,309 @@
# Dependencies
Control how dependencies are bundled or externalized.
## Overview
tsdown intelligently handles dependencies to keep your library lightweight while ensuring all necessary code is included.
## Default Behavior
### Auto-Externalized
These are **NOT bundled** by default:
- **`dependencies`** - Installed automatically with your package
- **`peerDependencies`** - User must install manually
### Conditionally Bundled
These are **bundled ONLY if imported**:
- **`devDependencies`** - Only if actually used in source code
- **Phantom dependencies** - In node_modules but not in package.json
## Configuration Options
### `external`
Mark dependencies as external (not bundled):
```ts
export default defineConfig({
entry: ['src/index.ts'],
external: [
'react', // Single package
'react-dom',
/^@myorg\//, // Regex pattern (all @myorg/* packages)
/^lodash/, // All lodash packages
],
})
```
### `noExternal`
Force dependencies to be bundled:
```ts
export default defineConfig({
entry: ['src/index.ts'],
noExternal: [
'some-package', // Bundle this even if in dependencies
'vendor-lib',
],
})
```
### `skipNodeModulesBundle`
Skip resolving and bundling ALL node_modules:
```ts
export default defineConfig({
entry: ['src/index.ts'],
skipNodeModulesBundle: true,
})
```
**Result:** No dependencies from node_modules are parsed or bundled.
## Common Patterns
### React Component Library
```ts
export default defineConfig({
entry: ['src/index.tsx'],
format: ['esm', 'cjs'],
external: [
'react',
'react-dom',
/^react\//, // react/jsx-runtime, etc.
],
dts: true,
})
```
### Utility Library with Shared Deps
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
// Bundle lodash utilities
noExternal: ['lodash-es'],
dts: true,
})
```
### Monorepo Package
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
external: [
/^@mycompany\//, // Don't bundle other workspace packages
],
dts: true,
})
```
### CLI Tool (Bundle Everything)
```ts
export default defineConfig({
entry: ['src/cli.ts'],
format: ['esm'],
platform: 'node',
// Bundle all dependencies for standalone CLI
noExternal: [/.*/],
shims: true,
})
```
### Library with Specific Externals
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
external: [
'vue',
'@vue/runtime-core',
'@vue/reactivity',
],
dts: true,
})
```
## Declaration Files
Dependency handling for `.d.ts` files follows the same rules as JavaScript.
### Complex Type Resolution
Use TypeScript resolver for complex third-party types:
```ts
export default defineConfig({
entry: ['src/index.ts'],
dts: {
resolver: 'tsc', // Use TypeScript resolver instead of Oxc
},
})
```
**When to use `tsc` resolver:**
- Types in `@types/*` packages with non-standard naming (e.g., `@types/babel__generator`)
- Complex type dependencies
- Issues with default Oxc resolver
**Trade-off:** `tsc` is slower but more compatible.
## CLI Usage
### External
```bash
tsdown --external react --external react-dom
tsdown --external '/^@myorg\/.*/'
```
### No External
```bash
tsdown --no-external some-package
```
## Examples by Use Case
### Framework Component
```ts
// Don't bundle framework
export default defineConfig({
external: ['vue', 'react', 'solid-js', 'svelte'],
})
```
### Standalone App
```ts
// Bundle everything
export default defineConfig({
noExternal: [/.*/],
skipNodeModulesBundle: false,
})
```
### Shared Library
```ts
// Bundle only specific utils
export default defineConfig({
external: [/.*/], // External by default
noExternal: ['tiny-utils'], // Except this one
})
```
### Monorepo Package
```ts
// External workspace packages, bundle utilities
export default defineConfig({
external: [
/^@workspace\//, // Other workspace packages
'react',
'react-dom',
],
noExternal: [
'lodash-es', // Bundle utility libraries
],
})
```
## Troubleshooting
### Dependency Bundled Unexpectedly
Check if it's in `devDependencies` and imported. Move to `dependencies`:
```json
{
"dependencies": {
"should-be-external": "^1.0.0"
}
}
```
Or explicitly externalize:
```ts
export default defineConfig({
external: ['should-be-external'],
})
```
### Missing Dependency at Runtime
Ensure it's in `dependencies` or `peerDependencies`:
```json
{
"dependencies": {
"needed-package": "^1.0.0"
}
}
```
Or bundle it:
```ts
export default defineConfig({
noExternal: ['needed-package'],
})
```
### Type Resolution Errors
Use TypeScript resolver for complex types:
```ts
export default defineConfig({
dts: {
resolver: 'tsc',
},
})
```
## Summary
**Default behavior:**
- `dependencies` & `peerDependencies` → External
- `devDependencies` & phantom deps → Bundled if imported
**Override:**
- `external` → Force external
- `noExternal` → Force bundled
- `skipNodeModulesBundle` → Skip all node_modules
**Declaration files:**
- Same bundling logic as JavaScript
- Use `resolver: 'tsc'` for complex types
## Tips
1. **Keep dependencies external** for libraries
2. **Bundle everything** for standalone CLIs
3. **Use regex patterns** for namespaced packages
4. **Check bundle size** to verify external/bundled split
5. **Test with fresh install** to catch missing dependencies
6. **Use tsc resolver** only when needed (slower)
## Related Options
- [External](option-dependencies.md) - This page
- [Platform](option-platform.md) - Runtime environment
- [Output Format](option-output-format.md) - Module formats
- [DTS](option-dts.md) - Type declarations

View File

@@ -0,0 +1,251 @@
# TypeScript Declaration Files
Generate `.d.ts` type declaration files for your library.
## Overview
tsdown uses [rolldown-plugin-dts](https://github.com/sxzz/rolldown-plugin-dts) to generate and bundle TypeScript declaration files.
**Requirements:**
- TypeScript must be installed in your project
## Enabling DTS Generation
### Auto-Enabled
DTS generation is **automatically enabled** if `package.json` contains:
- `types` field, or
- `typings` field
### Manual Enable
#### CLI
```bash
tsdown --dts
```
#### Config File
```ts
export default defineConfig({
dts: true,
})
```
## Performance
### With `isolatedDeclarations` (Recommended)
**Extremely fast** - uses oxc-transform for generation.
```json
// tsconfig.json
{
"compilerOptions": {
"isolatedDeclarations": true
}
}
```
### Without `isolatedDeclarations`
Falls back to TypeScript compiler. Reliable but slower.
## Declaration Maps
Map `.d.ts` files back to original `.ts` sources (useful for monorepos).
### Enable in tsconfig.json
```json
{
"compilerOptions": {
"declarationMap": true
}
}
```
### Enable in tsdown Config
```ts
export default defineConfig({
dts: {
sourcemap: true,
},
})
```
## Advanced Options
### Custom Compiler Options
Override TypeScript compiler options:
```ts
export default defineConfig({
dts: {
compilerOptions: {
removeComments: false,
},
},
})
```
## Build Process
- **ESM format**: `.js` and `.d.ts` files generated in same build
- **CJS format**: Separate build process for `.d.ts` files
## Common Patterns
### Basic Library
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
})
```
Output:
- `dist/index.mjs`
- `dist/index.cjs`
- `dist/index.d.ts`
### Multiple Entry Points
```ts
export default defineConfig({
entry: {
index: 'src/index.ts',
utils: 'src/utils.ts',
},
format: ['esm', 'cjs'],
dts: true,
})
```
Output:
- `dist/index.mjs`, `dist/index.cjs`, `dist/index.d.ts`
- `dist/utils.mjs`, `dist/utils.cjs`, `dist/utils.d.ts`
### With Monorepo Support
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: {
sourcemap: true, // Enable declaration maps
},
})
```
### Fast Build (Isolated Declarations)
```json
// tsconfig.json
{
"compilerOptions": {
"isolatedDeclarations": true,
"declaration": true,
"declarationMap": true
}
}
```
```ts
// tsdown.config.ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true, // Will use fast oxc-transform
})
```
## Troubleshooting
### Missing Types
Ensure TypeScript is installed:
```bash
pnpm add -D typescript
```
### Slow Generation
Enable `isolatedDeclarations` in `tsconfig.json` for faster builds.
### Declaration Errors
Check that all exports have explicit types (required for `isolatedDeclarations`).
### Report Issues
For DTS-specific issues, report to [rolldown-plugin-dts](https://github.com/sxzz/rolldown-plugin-dts/issues).
### Vue Support
Enable Vue component type generation (requires `vue-tsc`):
```ts
export default defineConfig({
dts: {
vue: true,
},
})
```
### Oxc Transform
Control Oxc usage for declaration generation:
```ts
export default defineConfig({
dts: {
oxc: true, // Use oxc-transform (fast, requires isolatedDeclarations)
},
})
```
### Custom TSConfig
Specify a different tsconfig for DTS generation:
```ts
export default defineConfig({
dts: {
tsconfig: './tsconfig.build.json',
},
})
```
## Available DTS Options
| Option | Type | Description |
|--------|------|-------------|
| `sourcemap` | `boolean` | Generate declaration source maps |
| `compilerOptions` | `object` | Override TypeScript compiler options |
| `vue` | `boolean` | Enable Vue type generation (requires vue-tsc) |
| `oxc` | `boolean` | Use oxc-transform for fast generation |
| `tsconfig` | `string` | Path to tsconfig file |
| `resolver` | `'oxc' \| 'tsc'` | Module resolver: `'oxc'` (default, fast) or `'tsc'` (more compatible) |
| `cjsDefault` | `boolean` | CJS default export handling |
| `sideEffects` | `boolean` | Preserve side effects in declarations |
## Tips
1. **Always enable DTS** for TypeScript libraries
2. **Use isolatedDeclarations** for fast builds
3. **Enable declaration maps** in monorepos
4. **Ensure explicit types** for all exports
5. **Install TypeScript** as dev dependency
## Related Options
- [Entry](option-entry.md) - Configure entry points
- [Output Format](option-output-format.md) - Multiple output formats
- [Target](option-target.md) - JavaScript version

View File

@@ -0,0 +1,211 @@
# Entry Points
Configure which files to bundle as entry points.
## Overview
Entry points are the starting files for the bundling process. Each entry point generates a separate bundle.
## Usage Patterns
### CLI
```bash
# Single entry
tsdown src/index.ts
# Multiple entries
tsdown src/index.ts src/cli.ts
# Glob patterns
tsdown 'src/*.ts'
```
### Config File
#### Single Entry
```ts
export default defineConfig({
entry: 'src/index.ts',
})
```
#### Multiple Entries (Array)
```ts
export default defineConfig({
entry: ['src/entry1.ts', 'src/entry2.ts'],
})
```
#### Named Entries (Object)
```ts
export default defineConfig({
entry: {
main: 'src/index.ts',
utils: 'src/utils.ts',
cli: 'src/cli.ts',
},
})
```
Output files will match the keys:
- `dist/main.mjs`
- `dist/utils.mjs`
- `dist/cli.mjs`
## Glob Patterns
Match multiple files dynamically using glob patterns:
### All TypeScript Files
```ts
export default defineConfig({
entry: 'src/**/*.ts',
})
```
### Exclude Test Files
```ts
export default defineConfig({
entry: ['src/*.ts', '!src/*.test.ts'],
})
```
### Object Entries with Glob Patterns
Use glob wildcards (`*`) in both keys and values. The `*` in the key acts as a placeholder replaced with the matched file name (without extension):
```ts
export default defineConfig({
entry: {
// Maps src/foo.ts → dist/lib/foo.js, src/bar.ts → dist/lib/bar.js
'lib/*': 'src/*.ts',
},
})
```
#### Negation Patterns in Object Entries
Values can be an array with negation patterns (`!`):
```ts
export default defineConfig({
entry: {
'hooks/*': ['src/hooks/*.ts', '!src/hooks/index.ts'],
},
})
```
Multiple positive and negation patterns:
```ts
export default defineConfig({
entry: {
'utils/*': [
'src/utils/*.ts',
'src/utils/*.tsx',
'!src/utils/index.ts',
'!src/utils/internal.ts',
],
},
})
```
**Warning:** Multiple positive patterns in an array value must share the same base directory.
### Mixed Entries
Mix strings, glob patterns, and object entries in an array:
```ts
export default defineConfig({
entry: [
'src/*',
'!src/foo.ts',
{ main: 'index.ts' },
{ 'lib/*': ['src/*.ts', '!src/bar.ts'] },
],
})
```
Object entries take precedence when output names conflict.
### Windows Compatibility
Use forward slashes `/` instead of backslashes `\` on Windows:
```ts
// ✅ Correct
entry: 'src/utils/*.ts'
// ❌ Wrong on Windows
entry: 'src\\utils\\*.ts'
```
## Common Patterns
### Library with Main Export
```ts
export default defineConfig({
entry: 'src/index.ts',
format: ['esm', 'cjs'],
dts: true,
})
```
### Library with Multiple Exports
```ts
export default defineConfig({
entry: {
index: 'src/index.ts',
client: 'src/client.ts',
server: 'src/server.ts',
},
format: ['esm', 'cjs'],
dts: true,
})
```
### CLI Tool
```ts
export default defineConfig({
entry: {
cli: 'src/cli.ts',
},
format: ['esm'],
platform: 'node',
})
```
### Preserve Directory Structure
Use with `unbundle: true` to keep file structure:
```ts
export default defineConfig({
entry: ['src/**/*.ts', '!**/*.test.ts'],
unbundle: true,
format: ['esm'],
dts: true,
})
```
This will output files matching the source structure:
- `src/index.ts``dist/index.mjs`
- `src/utils/helper.ts``dist/utils/helper.mjs`
## Tips
1. **Use glob patterns** for multiple related files
2. **Use object syntax** for custom output names
3. **Exclude test files** with negation patterns `!**/*.test.ts`
4. **Combine with unbundle** to preserve directory structure
5. **Use named entries** for better control over output filenames

View File

@@ -0,0 +1,127 @@
# Package Validation (publint & attw)
Validate your package configuration and type declarations before publishing.
## Overview
tsdown integrates with [publint](https://publint.dev/) and [Are the types wrong?](https://arethetypeswrong.github.io/) (attw) to catch common packaging issues. Both are optional dependencies.
## Installation
```bash
# publint only
npm install -D publint
# attw only
npm install -D @arethetypeswrong/core
# both
npm install -D publint @arethetypeswrong/core
```
## publint
Checks that `package.json` fields (`exports`, `main`, `module`, `types`) match your actual output files.
### Enable
```ts
export default defineConfig({
publint: true,
})
```
### Configuration
```ts
export default defineConfig({
publint: {
level: 'error', // 'warning' | 'error' | 'suggestion'
},
})
```
### CLI
```bash
tsdown --publint
```
## attw (Are the types wrong?)
Verifies TypeScript declarations are correct across different module resolution strategies (`node10`, `node16`, `bundler`).
### Enable
```ts
export default defineConfig({
attw: true,
})
```
### Configuration
```ts
export default defineConfig({
attw: {
profile: 'node16', // 'strict' | 'node16' | 'esm-only'
level: 'error', // 'warn' | 'error'
ignoreRules: ['false-cjs', 'cjs-resolves-to-esm'],
},
})
```
### Profiles
| Profile | Description |
|---------|-------------|
| `strict` | Requires all resolutions to pass (default) |
| `node16` | Ignores `node10` resolution failures |
| `esm-only` | Ignores `node10` and `node16-cjs` resolution failures |
### Ignore Rules
Suppress specific problem types with `ignoreRules`:
| Rule | Description |
|------|-------------|
| `no-resolution` | Module could not be resolved |
| `untyped-resolution` | Resolution succeeded but has no types |
| `false-cjs` | Types indicate CJS but implementation is ESM |
| `false-esm` | Types indicate ESM but implementation is CJS |
| `cjs-resolves-to-esm` | CJS resolution points to an ESM module |
| `fallback-condition` | A fallback/wildcard condition was used |
| `cjs-only-exports-default` | CJS module only exports a default |
| `named-exports` | Named exports mismatch between types and implementation |
| `false-export-default` | Types declare a default export that doesn't exist |
| `missing-export-equals` | Types are missing `export =` for CJS |
| `unexpected-module-syntax` | File uses unexpected module syntax |
| `internal-resolution-error` | Internal resolution error in type checking |
### CLI
```bash
tsdown --attw
```
## CI Integration
Both tools support CI-aware options:
```ts
export default defineConfig({
publint: 'ci-only',
attw: {
enabled: 'ci-only',
profile: 'node16',
level: 'error',
},
})
```
Both tools require a `package.json` in your project directory.
## Related Options
- [CI Environment](advanced-ci.md) - CI-aware option details
- [Package Exports](option-package-exports.md) - Auto-generate exports field

View File

@@ -0,0 +1,91 @@
# Log Level
Control the verbosity of build output.
## Overview
The `logLevel` option controls how much information tsdown displays during the build process.
## Type
```ts
logLevel?: 'silent' | 'error' | 'warn' | 'info'
```
**Default:** `'info'`
## Basic Usage
### CLI
```bash
# Suppress all output
tsdown --log-level silent
# Only show errors
tsdown --log-level error
# Show warnings and errors
tsdown --log-level warn
# Show all info (default)
tsdown --log-level info
```
### Config File
```ts
export default defineConfig({
entry: ['src/index.ts'],
logLevel: 'error',
})
```
## Available Levels
| Level | Shows | Use Case |
|-------|-------|----------|
| `silent` | Nothing | CI/CD pipelines, scripting |
| `error` | Errors only | Minimal output |
| `warn` | Warnings + errors | Standard CI/CD |
| `info` | All messages | Development (default) |
## Common Patterns
### CI/CD Pipeline
```ts
export default defineConfig({
entry: ['src/index.ts'],
logLevel: 'error', // Only show errors in CI
})
```
### Scripting
```ts
export default defineConfig({
entry: ['src/index.ts'],
logLevel: 'silent', // No output for automation
})
```
## Fail on Warnings
The `failOnWarn` option controls whether warnings cause the build to exit with a non-zero code. Defaults to `'ci-only'` — warnings fail the build in CI but not locally.
```ts
export default defineConfig({
failOnWarn: 'ci-only', // Default: fail on warnings only in CI
// failOnWarn: true, // Always fail on warnings
// failOnWarn: false, // Never fail on warnings
})
```
See [CI Environment](advanced-ci.md) for more about CI-aware options.
## Related Options
- [CI Environment](advanced-ci.md) - CI-aware option details
- [CLI Reference](reference-cli.md) - All CLI options
- [Config File](option-config-file.md) - Configuration setup

View File

@@ -0,0 +1,177 @@
# Minification
Compress code to reduce bundle size.
## Overview
Minification removes unnecessary characters (whitespace, comments) and optimizes code for production, reducing bundle size and improving load times.
**Note:** Uses [Oxc minifier](https://oxc.rs/docs/contribute/minifier) internally. The minifier is currently in alpha.
## Type
```ts
minify?: boolean | 'dce-only' | MinifyOptions
```
- `true` — Enable full minification (whitespace removal, mangling, compression)
- `false` — Disable minification (default)
- `'dce-only'` — Only perform dead code elimination without full minification
- `MinifyOptions` — Pass detailed options to the Oxc minifier
## Basic Usage
### CLI
```bash
# Enable minification
tsdown --minify
# Disable minification
tsdown --no-minify
```
**Note:** The CLI `--minify` flag is a boolean toggle. For `'dce-only'` mode or advanced options, use the config file.
### Config File
```ts
export default defineConfig({
entry: ['src/index.ts'],
minify: true,
})
```
### DCE-Only Mode
Remove dead code without full minification (keeps readable output):
```ts
export default defineConfig({
entry: ['src/index.ts'],
minify: 'dce-only',
})
```
## Example Output
### Without Minification
```js
// dist/index.mjs
const x = 1
function hello(x$1) {
console.log('Hello World')
console.log(x$1)
}
hello(x)
```
### With Minification
```js
// dist/index.mjs
const e=1;function t(e){console.log(`Hello World`),console.log(e)}t(e);
```
## Common Patterns
### Production Build
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
minify: true,
clean: true,
})
```
### Conditional Minification
```ts
export default defineConfig((options) => ({
entry: ['src/index.ts'],
format: ['esm'],
minify: !options.watch, // Only minify in production
}))
```
### Browser Library
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['iife'],
platform: 'browser',
globalName: 'MyLib',
minify: true,
})
```
### Multiple Builds
```ts
export default defineConfig([
// Development build
{
entry: ['src/index.ts'],
format: ['esm'],
minify: false,
outDir: 'dist/dev',
},
// Production build
{
entry: ['src/index.ts'],
format: ['esm'],
minify: true,
outDir: 'dist/prod',
},
])
```
## CLI Examples
```bash
# Production build with minification
tsdown --minify --clean
# Multiple formats with minification
tsdown --format esm --format cjs --minify
# Conditional minification (only when not watching)
tsdown --minify # Or omit --watch
```
## Tips
1. **Use `minify: true`** for production builds
2. **Use `'dce-only'`** to remove dead code while keeping output readable
3. **Skip minification** during development for faster rebuilds
4. **Combine with tree shaking** for best results
5. **Test minified output** thoroughly (Oxc minifier is in alpha)
## Troubleshooting
### Minified Code Has Bugs
Oxc minifier is in alpha and may have issues:
1. **Use DCE-only mode**: `minify: 'dce-only'`
2. **Report bug** to [Oxc project](https://github.com/oxc-project/oxc/issues)
3. **Disable minification**: `minify: false`
### Unexpected Output
- **Test unminified** first to isolate issue
- **Check source maps** for debugging
- **Verify target compatibility**
## Related Options
- [Tree Shaking](option-tree-shaking.md) - Remove unused code
- [Target](option-target.md) - Syntax transformations
- [Output Format](option-output-format.md) - Module formats
- [Sourcemap](option-sourcemap.md) - Debug information

View File

@@ -0,0 +1,270 @@
# Output Directory
Configure the output directory for bundled files.
## Overview
By default, tsdown outputs bundled files to the `dist` directory. You can customize this location using the `outDir` option.
## Basic Usage
### CLI
```bash
# Default output to dist/
tsdown
# Custom output directory
tsdown --out-dir build
tsdown -d lib
```
### Config File
```ts
export default defineConfig({
entry: ['src/index.ts'],
outDir: 'build',
})
```
## Common Patterns
### Standard Library
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
outDir: 'dist', // Default
dts: true,
})
```
**Output:**
```
dist/
├── index.mjs
├── index.cjs
└── index.d.ts
```
### Separate Directories by Format
```ts
export default defineConfig([
{
entry: ['src/index.ts'],
format: ['esm'],
outDir: 'dist/esm',
},
{
entry: ['src/index.ts'],
format: ['cjs'],
outDir: 'dist/cjs',
},
])
```
**Output:**
```
dist/
├── esm/
│ └── index.js
└── cjs/
└── index.js
```
### Monorepo Package
```ts
export default defineConfig({
entry: ['src/index.ts'],
outDir: 'lib', // Custom directory
clean: true,
})
```
### Build to Root
```ts
export default defineConfig({
entry: ['src/index.ts'],
outDir: '.', // Output to project root (not recommended)
clean: false, // Don't clean root!
})
```
**Warning:** Be careful when outputting to root to avoid deleting important files.
## Output Extensions
### Custom Extensions
Use `outExtensions` to control file extensions:
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
outDir: 'dist',
outExtensions({ format }) {
return {
js: format === 'esm' ? '.mjs' : '.cjs',
}
},
})
```
### Default Extensions
| Format | Default Extension | With `type: "module"` |
|--------|-------------------|----------------------|
| `esm` | `.mjs` | `.js` |
| `cjs` | `.cjs` | `.js` |
| `iife` | `.global.js` | `.global.js` |
| `umd` | `.umd.js` | `.umd.js` |
### ESM with .js Extension
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm'],
outExtensions: () => ({ js: '.js' }),
})
```
Requires `"type": "module"` in package.json.
## File Naming
### Entry Names
Control output filenames based on entry names:
```ts
export default defineConfig({
entry: {
index: 'src/index.ts',
utils: 'src/utils.ts',
},
outDir: 'dist',
})
```
**Output:**
```
dist/
├── index.mjs
└── utils.mjs
```
### Glob Entry
```ts
export default defineConfig({
entry: ['src/**/*.ts', '!**/*.test.ts'],
outDir: 'dist',
unbundle: true, // Preserve structure
})
```
**Output:**
```
dist/
├── index.mjs
├── utils/
│ └── helper.mjs
└── components/
└── button.mjs
```
## Multiple Builds
### Same Output Directory
```ts
export default defineConfig([
{
entry: ['src/index.ts'],
outDir: 'dist',
clean: true, // Clean first
},
{
entry: ['src/cli.ts'],
outDir: 'dist',
clean: false, // Don't clean again
},
])
```
### Different Output Directories
```ts
export default defineConfig([
{
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
outDir: 'dist/lib',
},
{
entry: ['src/cli.ts'],
format: ['esm'],
outDir: 'dist/bin',
},
])
```
## CLI Examples
```bash
# Default
tsdown
# Custom directory
tsdown --out-dir build
tsdown -d lib
# Nested directory
tsdown --out-dir dist/lib
# With other options
tsdown --out-dir build --format esm,cjs --dts
```
## Tips
1. **Use default `dist`** for standard projects
2. **Be careful with root** - avoid `outDir: '.'`
3. **Clean before build** - use `clean: true`
4. **Consistent naming** - match your project conventions
5. **Separate by format** if needed for clarity
6. **Check .gitignore** - ensure output dir is ignored
## Troubleshooting
### Files Not in Expected Location
- Check `outDir` config
- Verify build completed successfully
- Look for typos in path
### Files Deleted Unexpectedly
- Check if `clean: true`
- Ensure outDir doesn't overlap with source
- Don't use root as outDir
### Permission Errors
- Check write permissions
- Ensure directory isn't locked
- Try different location
## Related Options
- [Cleaning](option-cleaning.md) - Clean output directory
- [Entry](option-entry.md) - Entry points
- [Output Format](option-output-format.md) - Module formats
- [Unbundle](option-unbundle.md) - Preserve structure

View File

@@ -0,0 +1,179 @@
# Output Format
Configure the module format(s) for generated bundles.
## Overview
tsdown can generate bundles in multiple formats. Default is ESM.
## Available Formats
| Format | Description | Use Case |
|--------|-------------|----------|
| `esm` | ECMAScript Module (default) | Modern Node.js, browsers, Deno |
| `cjs` | CommonJS | Legacy Node.js, require() |
| `iife` | Immediately Invoked Function Expression | Browser `<script>` tags |
| `umd` | Universal Module Definition | AMD, CommonJS, and globals |
## Usage
### CLI
```bash
# Single format
tsdown --format esm
# Multiple formats
tsdown --format esm --format cjs
# Or comma-separated
tsdown --format esm,cjs
```
### Config File
#### Single Format
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: 'esm',
})
```
#### Multiple Formats
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
})
```
## Per-Format Configuration
Override options for specific formats:
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: {
esm: {
target: ['es2015'],
},
cjs: {
target: ['node20'],
},
},
})
```
This allows different targets, platforms, or other settings per format.
## Common Patterns
### Modern Library (ESM + CJS)
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
})
```
Output:
- `dist/index.mjs` (ESM)
- `dist/index.cjs` (CJS)
- `dist/index.d.ts` (Types)
### Browser Library (IIFE)
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['iife'],
globalName: 'MyLib',
platform: 'browser',
minify: true,
})
```
Output: `dist/index.global.js` (IIFE with global `MyLib`)
### Universal Library (UMD)
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['umd'],
globalName: 'MyLib',
platform: 'neutral',
})
```
Works with AMD, CommonJS, and browser globals.
### Node.js Package (CJS + ESM)
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
platform: 'node',
dts: true,
shims: true, // Add __dirname, __filename for CJS compat
})
```
### Framework Component Library
```ts
export default defineConfig({
entry: ['src/index.tsx'],
format: ['esm', 'cjs'],
external: ['react', 'react-dom'], // Don't bundle dependencies
dts: true,
})
```
## Format-Specific Outputs
### File Extensions
| Format | Extension |
|--------|-----------|
| ESM | `.mjs` or `.js` (with `"type": "module"`) |
| CJS | `.cjs` or `.js` (without `"type": "module"`) |
| IIFE | `.global.js` |
| UMD | `.umd.js` |
### Customize Extensions
Use `outExtensions` to override:
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
outExtensions: ({ format }) => ({
js: format === 'esm' ? '.js' : '.cjs',
}),
})
```
## Tips
1. **Use ESM + CJS** for maximum compatibility
2. **Use IIFE** for browser-only libraries
3. **Use UMD** for universal compatibility (less common now)
4. **Externalize dependencies** to avoid bundling framework code
5. **Add shims** for CJS compatibility when using Node.js APIs
6. **Set globalName** for IIFE/UMD formats
## Related Options
- [Target](option-target.md) - Set JavaScript version
- [Platform](option-platform.md) - Set platform (node, browser, neutral)
- [Shims](option-shims.md) - Add ESM/CJS compatibility
- [Output Directory](option-output-directory.md) - Customize output paths

View File

@@ -0,0 +1,320 @@
# Auto-Generate Package Exports
Automatically generate package.json exports field from build output.
## Overview
tsdown can automatically infer and generate the `exports`, `main`, `module`, and `types` fields in your `package.json` based on your build outputs.
**Status:** Experimental - review before publishing.
## Basic Usage
### CLI
```bash
tsdown --exports
```
### Config File
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
exports: true,
})
```
## What Gets Generated
### Single Entry
**Config:**
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
exports: true,
})
```
**Generated in package.json:**
```json
{
"main": "./dist/index.cjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
}
}
}
```
### Multiple Entries
**Config:**
```ts
export default defineConfig({
entry: {
index: 'src/index.ts',
utils: 'src/utils.ts',
},
format: ['esm', 'cjs'],
dts: true,
exports: true,
})
```
**Generated in package.json:**
```json
{
"main": "./dist/index.cjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
},
"./utils": {
"types": "./dist/utils.d.ts",
"import": "./dist/utils.mjs",
"require": "./dist/utils.cjs"
}
}
}
```
## Export All Files
Include all output files, not just entry points:
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
exports: {
all: true,
},
})
```
**Result:** All `.mjs`, `.cjs`, and `.d.ts` files will be added to exports.
## Dev-Time Source Linking
### Dev Exports
Link to source files during development:
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
exports: {
devExports: true,
},
})
```
**Generated:**
```json
{
"exports": {
".": "./src/index.ts" // Points to source
},
"publishConfig": {
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
}
}
}
}
```
**Note:** Supported by pnpm/yarn, not npm.
### Conditional Dev Exports
Use specific condition for dev exports:
```ts
export default defineConfig({
exports: {
devExports: 'development',
},
})
```
**Generated:**
```json
{
"exports": {
".": {
"development": "./src/index.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
}
}
}
```
**Use with TypeScript customConditions:**
```json
// tsconfig.json
{
"compilerOptions": {
"customConditions": ["development"]
}
}
```
## Custom Exports
Add custom export mappings:
```ts
export default defineConfig({
entry: ['src/index.ts'],
exports: {
customExports(pkg, context) {
// Add custom export
pkg['./foo'] = './dist/foo.js'
// Add package.json export
pkg['./package.json'] = './package.json'
return pkg
},
},
})
```
## Common Patterns
### Complete Library Setup
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
exports: true,
clean: true,
})
```
### Multiple Exports with Dev Mode
```ts
export default defineConfig({
entry: {
index: 'src/index.ts',
client: 'src/client.ts',
server: 'src/server.ts',
},
format: ['esm', 'cjs'],
dts: true,
exports: {
all: false, // Only entries
devExports: 'development',
},
})
```
### Monorepo Package
```ts
export default defineConfig({
workspace: 'packages/*',
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
exports: true, // Generate for each package
})
```
## Validation
### Enable Publint
Validate generated exports:
```bash
tsdown --exports --publint
```
Or in config:
```ts
export default defineConfig({
exports: true,
publint: true, // Validate exports
})
```
## Tips
1. **Review before publishing** - Check generated fields
2. **Use with publint** - Validate exports field
3. **Enable for libraries** - Especially with multiple exports
4. **Use devExports** - Better DX during development
5. **Test exports** - Verify imports work correctly
## Troubleshooting
### Exports Not Generated
- Ensure `exports: true` is set
- Check build completed successfully
- Verify output files exist
### Wrong Export Paths
- Check `outDir` configuration
- Verify entry names match expectations
- Review `format` settings
### Dev Exports Not Working
- Only supported by pnpm/yarn
- Check package manager
- Use `publishConfig` for publishing
### Types Not Exported
- Enable `dts: true`
- Ensure TypeScript is installed
- Check `.d.ts` files are generated
## CLI Examples
```bash
# Generate exports
tsdown --exports
# With publint validation
tsdown --exports --publint
# Export all files
tsdown --exports
# With dev exports
tsdown --exports
```
## Related Options
- [Entry](option-entry.md) - Configure entry points
- [Output Format](option-output-format.md) - Module formats
- [DTS](option-dts.md) - Type declarations

View File

@@ -0,0 +1,254 @@
# Platform
Target runtime environment for bundled code.
## Overview
Platform determines the runtime environment and affects module resolution, built-in handling, and optimizations.
## Available Platforms
| Platform | Runtime | Built-ins | Use Case |
|----------|---------|-----------|----------|
| `node` | Node.js (default) | Resolved automatically | Server-side, CLIs, tooling |
| `browser` | Web browsers | Warning if used | Front-end applications |
| `neutral` | Platform-agnostic | No assumptions | Universal libraries |
## Usage
### CLI
```bash
tsdown --platform node # Default
tsdown --platform browser
tsdown --platform neutral
```
### Config File
```ts
export default defineConfig({
entry: ['src/index.ts'],
platform: 'browser',
})
```
## Platform Details
### Node Platform
**Default platform** for server-side and tooling.
```ts
export default defineConfig({
entry: ['src/index.ts'],
platform: 'node',
})
```
**Characteristics:**
- Node.js built-ins (fs, path, etc.) resolved automatically
- Optimized for Node.js runtime
- Compatible with Deno and Bun
- Default mainFields: `['main', 'module']`
### Browser Platform
For web applications running in browsers.
```ts
export default defineConfig({
entry: ['src/index.ts'],
platform: 'browser',
format: ['esm'],
})
```
**Characteristics:**
- Warnings if Node.js built-ins are used
- May require polyfills for Node APIs
- Optimized for browser environments
- Default mainFields: `['browser', 'module', 'main']`
### Neutral Platform
Platform-agnostic for universal libraries.
```ts
export default defineConfig({
entry: ['src/index.ts'],
platform: 'neutral',
format: ['esm'],
})
```
**Characteristics:**
- No runtime assumptions
- No automatic built-in resolution
- Relies on `exports` field only
- Default mainFields: `[]`
- Full control over runtime behavior
## CJS Format Limitation
**CJS format always uses `node` platform** and cannot be changed.
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['cjs'],
platform: 'browser', // Ignored for CJS
})
```
See [rolldown PR #4693](https://github.com/rolldown/rolldown/pull/4693#issuecomment-2912229545) for details.
## Module Resolution
### Main Fields
Different platforms check different `package.json` fields:
| Platform | mainFields | Priority |
|----------|------------|----------|
| `node` | `['main', 'module']` | main → module |
| `browser` | `['browser', 'module', 'main']` | browser → module → main |
| `neutral` | `[]` | Only `exports` field |
### Neutral Platform Resolution
When using `neutral`, packages without `exports` field may fail to resolve:
```
Help: The "main" field here was ignored. Main fields must be configured
explicitly when using the "neutral" platform.
```
**Solution:** Configure mainFields explicitly:
```ts
export default defineConfig({
platform: 'neutral',
inputOptions: {
resolve: {
mainFields: ['module', 'main'],
},
},
})
```
## Common Patterns
### Node.js CLI Tool
```ts
export default defineConfig({
entry: ['src/cli.ts'],
format: ['esm'],
platform: 'node',
shims: true,
})
```
### Browser Library (IIFE)
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['iife'],
platform: 'browser',
globalName: 'MyLib',
minify: true,
})
```
### Universal Library
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm'],
platform: 'neutral',
inputOptions: {
resolve: {
mainFields: ['module', 'main'],
},
},
})
```
### React Component Library
```ts
export default defineConfig({
entry: ['src/index.tsx'],
format: ['esm', 'cjs'],
platform: 'browser',
external: ['react', 'react-dom'],
})
```
### Node.js + Browser Builds
```ts
export default defineConfig([
{
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
platform: 'node',
},
{
entry: ['src/browser.ts'],
format: ['esm'],
platform: 'browser',
},
])
```
## Troubleshooting
### Node Built-in Warnings (Browser)
When using Node.js APIs in browser builds:
```
Warning: Module "fs" has been externalized for browser compatibility
```
**Solutions:**
1. Use platform: 'node' if not browser-only
2. Add polyfills for Node APIs
3. Avoid Node.js built-ins in browser code
4. Use platform: 'neutral' with careful dependency management
### Module Resolution Issues (Neutral)
When packages don't resolve with `neutral`:
```ts
export default defineConfig({
platform: 'neutral',
inputOptions: {
resolve: {
mainFields: ['module', 'browser', 'main'],
conditions: ['import', 'require'],
},
},
})
```
## Tips
1. **Use `node`** for server-side and CLIs (default)
2. **Use `browser`** for front-end applications
3. **Use `neutral`** for universal libraries
4. **Configure mainFields** when using neutral platform
5. **CJS is always node** - use ESM for other platforms
6. **Test in target environment** to verify compatibility
## Related Options
- [Output Format](option-output-format.md) - Module formats
- [Target](option-target.md) - JavaScript version
- [Shims](option-shims.md) - ESM/CJS compatibility
- [Dependencies](option-dependencies.md) - External packages

View File

@@ -0,0 +1,297 @@
# Shims
Add compatibility between ESM and CommonJS module systems.
## Overview
Shims provide small pieces of code that bridge the gap between CommonJS (CJS) and ECMAScript Modules (ESM), enabling cross-module-system compatibility.
## What Shims Provide
### ESM Output (when enabled)
With `shims: true`, adds CommonJS variables to ESM:
- `__dirname` - Current directory path
- `__filename` - Current file path
### ESM Output (automatic)
Always added when using `require` in ESM on Node.js:
- `require` function via `createRequire(import.meta.url)`
### CJS Output (automatic)
Always added to CommonJS output:
- `import.meta.url`
- `import.meta.dirname`
- `import.meta.filename`
## Usage
### CLI
```bash
tsdown --shims
```
### Config File
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm'],
shims: true,
})
```
## Generated Code
### ESM with Shims
**Source:**
```ts
console.log(__dirname)
console.log(__filename)
```
**Output (shims: true):**
```js
import { fileURLToPath } from 'node:url'
import { dirname } from 'node:path'
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
console.log(__dirname)
console.log(__filename)
```
### ESM with require
**Source:**
```ts
const mod = require('some-module')
```
**Output (automatic on Node.js):**
```js
import { createRequire } from 'node:module'
const require = createRequire(import.meta.url)
const mod = require('some-module')
```
### CJS with import.meta
**Source:**
```ts
console.log(import.meta.url)
console.log(import.meta.dirname)
```
**Output (automatic):**
```js
const import_meta = {
url: require('url').pathToFileURL(__filename).toString(),
dirname: __dirname,
filename: __filename
}
console.log(import_meta.url)
console.log(import_meta.dirname)
```
## Common Patterns
### Node.js CLI Tool
```ts
export default defineConfig({
entry: ['src/cli.ts'],
format: ['esm'],
platform: 'node',
shims: true, // Add __dirname, __filename
})
```
### Dual Format Library
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
platform: 'node',
shims: true, // ESM gets __dirname/__filename
// CJS gets import.meta.* (automatic)
})
```
### Server-Side Code
```ts
export default defineConfig({
entry: ['src/server.ts'],
format: ['esm'],
platform: 'node',
shims: true,
external: [/.*/], // External all deps
})
```
### File System Operations
```ts
// Source code
import { readFileSync } from 'fs'
import { join } from 'path'
// Read file relative to current module
const content = readFileSync(join(__dirname, 'data.json'), 'utf-8')
```
```ts
// tsdown config
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm'],
shims: true, // Enables __dirname
})
```
## When to Use Shims
### Use `shims: true` when:
- ✅ Building Node.js tools/CLIs
- ✅ Code uses `__dirname` or `__filename`
- ✅ Need file system operations relative to module
- ✅ Migrating from CommonJS to ESM
- ✅ Need cross-format compatibility
### Don't need shims when:
- ❌ Browser-only code
- ❌ No file system operations
- ❌ Using only `import.meta.url`
- ❌ Pure ESM without CJS variables
## Performance Impact
### Runtime Overhead
Shims add minimal runtime overhead:
```js
// Added to output when shims enabled
import { fileURLToPath } from 'node:url'
import { dirname } from 'node:path'
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
```
### Tree Shaking
If `__dirname` or `__filename` are not used, they're automatically removed during bundling (no overhead).
## Platform Considerations
### Node.js Platform
```ts
export default defineConfig({
platform: 'node',
format: ['esm'],
shims: true, // Recommended for Node.js
})
```
- `require` shim added automatically
- `__dirname` and `__filename` available with `shims: true`
### Browser Platform
```ts
export default defineConfig({
platform: 'browser',
format: ['esm'],
shims: false, // Not needed for browser
})
```
- Shims not needed (no Node.js variables)
- Will cause warnings if Node.js APIs used
### Neutral Platform
```ts
export default defineConfig({
platform: 'neutral',
format: ['esm'],
shims: false, // Avoid platform-specific code
})
```
- Avoid shims for maximum portability
## CLI Examples
```bash
# Enable shims
tsdown --shims
# ESM with shims for Node.js
tsdown --format esm --platform node --shims
# Dual format with shims
tsdown --format esm --format cjs --shims
```
## Troubleshooting
### `__dirname is not defined`
Enable shims:
```ts
export default defineConfig({
shims: true,
})
```
### `require is not defined` in ESM
Automatic on Node.js platform. If not working:
```ts
export default defineConfig({
platform: 'node', // Ensure Node.js platform
})
```
### Import.meta not working in CJS
Automatic - no configuration needed. If still failing, check output format:
```ts
export default defineConfig({
format: ['cjs'], // Shims added automatically
})
```
## Tips
1. **Enable for Node.js tools** - Use `shims: true` for CLIs and servers
2. **Skip for browsers** - Not needed for browser code
3. **No overhead if unused** - Automatically tree-shaken
4. **Automatic require shim** - No config needed for `require` in ESM
5. **CJS shims automatic** - `import.meta.*` always available in CJS
## Related Options
- [Platform](option-platform.md) - Runtime environment
- [Output Format](option-output-format.md) - Module formats
- [Target](option-target.md) - Syntax transformations

View File

@@ -0,0 +1,301 @@
# Source Maps
Generate source maps for debugging bundled code.
## Overview
Source maps map minified/bundled code back to original source files, making debugging significantly easier by showing original line numbers and variable names.
## Basic Usage
### CLI
```bash
tsdown --sourcemap
# Or inline
tsdown --sourcemap inline
```
### Config File
```ts
export default defineConfig({
entry: ['src/index.ts'],
sourcemap: true,
})
```
## Source Map Types
### External (default)
Generates separate `.map` files:
```ts
export default defineConfig({
sourcemap: true, // or 'external'
})
```
**Output:**
- `dist/index.mjs`
- `dist/index.mjs.map`
**Pros:**
- Smaller bundle size
- Can be excluded from production
- Faster parsing
### Inline
Embeds source maps in the bundle:
```ts
export default defineConfig({
sourcemap: 'inline',
})
```
**Output:**
- `dist/index.mjs` (includes source map as data URL)
**Pros:**
- Single file deployment
- Guaranteed to be available
**Cons:**
- Larger bundle size
- Exposed in production
### Hidden
Generates map files without reference comment:
```ts
export default defineConfig({
sourcemap: 'hidden',
})
```
**Output:**
- `dist/index.mjs` (no `//# sourceMappingURL` comment)
- `dist/index.mjs.map`
**Use when:**
- You want maps for error reporting tools
- But don't want them exposed to users
## Auto-Enable Scenarios
### Declaration Maps
If `declarationMap` is enabled in `tsconfig.json`, source maps are automatically enabled:
```json
// tsconfig.json
{
"compilerOptions": {
"declarationMap": true
}
}
```
This also generates `.d.ts.map` files for TypeScript declarations.
## Common Patterns
### Development Build
```ts
export default defineConfig((options) => ({
entry: ['src/index.ts'],
sourcemap: options.watch, // Only in dev
minify: !options.watch,
}))
```
### Production with External Maps
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
sourcemap: true, // External maps
minify: true,
})
```
Deploy maps to separate error reporting service.
### Always Inline (Development Tool)
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm'],
sourcemap: 'inline',
})
```
### Per-Format Source Maps
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: {
esm: {
sourcemap: true,
},
iife: {
sourcemap: 'inline', // Inline for browser
},
},
})
```
### TypeScript Library with Declaration Maps
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
sourcemap: true,
dts: {
sourcemap: true, // Enable declaration maps
},
})
```
**Output:**
- `dist/index.mjs` + `dist/index.mjs.map`
- `dist/index.cjs` + `dist/index.cjs.map`
- `dist/index.d.ts` + `dist/index.d.ts.map`
## Benefits
### For Development
- **Faster debugging** - See original code in debugger
- **Better error messages** - Stack traces show original lines
- **Easier breakpoints** - Set breakpoints on source code
### For Production
- **Error reporting** - Send accurate error locations to services
- **Monitoring** - Track errors back to source
- **Support** - Help users report issues accurately
## Performance Impact
| Type | Bundle Size | Parse Speed | Debugging |
|------|-------------|-------------|-----------|
| None | Smallest | Fastest | Hard |
| External | Small | Fast | Easy |
| Inline | Largest | Slower | Easy |
| Hidden | Small | Fast | Tools only |
## CLI Examples
```bash
# Enable source maps
tsdown --sourcemap
# Inline source maps
tsdown --sourcemap inline
# Hidden source maps
tsdown --sourcemap hidden
# Development with source maps
tsdown --watch --sourcemap
# Production with external maps
tsdown --minify --sourcemap
# No source maps
tsdown --no-sourcemap
```
## Use Cases
### Local Development
```ts
export default defineConfig({
sourcemap: true,
minify: false,
})
```
### Production Build
```ts
export default defineConfig({
sourcemap: 'external', // Upload to error service
minify: true,
})
```
### Browser Library
```ts
export default defineConfig({
format: ['iife'],
platform: 'browser',
sourcemap: 'inline', // Self-contained
globalName: 'MyLib',
})
```
### Node.js CLI Tool
```ts
export default defineConfig({
format: ['esm'],
platform: 'node',
sourcemap: true,
shims: true,
})
```
## Troubleshooting
### Source Maps Not Working
1. **Check output** - Verify `.map` files are generated
2. **Check reference** - Look for `//# sourceMappingURL=` comment
3. **Check paths** - Ensure relative paths are correct
4. **Check tool** - Verify debugger/browser supports source maps
### Large Bundle Size
Use external source maps instead of inline:
```ts
export default defineConfig({
sourcemap: true, // Not 'inline'
})
```
### Source Not Found
- Ensure source files are accessible relative to map
- Check `sourceRoot` in generated map
- Verify paths in `sources` array
## Tips
1. **Use external maps** for production (smaller bundles)
2. **Use inline maps** for single-file tools
3. **Enable in development** for better DX
4. **Upload to error services** for production debugging
5. **Use hidden maps** when you want them for tools only
6. **Enable declaration maps** for TypeScript libraries
## Related Options
- [Minification](option-minification.md) - Code compression
- [DTS](option-dts.md) - TypeScript declarations
- [Watch Mode](option-watch-mode.md) - Development workflow
- [Target](option-target.md) - Syntax transformations

View File

@@ -0,0 +1,208 @@
# Target Environment
Configure JavaScript syntax transformations for target environments.
## Overview
The `target` option controls which JavaScript features are downleveled (transformed to older syntax) for compatibility.
**Important:** Only affects syntax transformations, not runtime polyfills.
## Default Behavior
tsdown auto-reads from `package.json`:
```json
// package.json
{
"engines": {
"node": ">=18.0.0"
}
}
```
Automatically sets `target` to `node18.0.0`.
If no `engines.node` field exists, behaves as if `target: false` (no transformations).
## Disabling Transformations
Set to `false` to preserve modern syntax:
```ts
export default defineConfig({
target: false,
})
```
**Result:**
- No JavaScript downleveling
- Modern features preserved (optional chaining `?.`, nullish coalescing `??`, etc.)
**Use when:**
- Targeting modern environments
- Handling transformations elsewhere
- Building libraries for further processing
## Setting Target
### CLI
```bash
# Single target
tsdown --target es2020
tsdown --target node20
# Multiple targets
tsdown --target chrome100 --target node20.18
# Disable
tsdown --no-target
```
### Config File
```ts
export default defineConfig({
entry: ['src/index.ts'],
target: 'es2020',
})
```
### Multiple Targets
```ts
export default defineConfig({
entry: ['src/index.ts'],
target: ['chrome100', 'safari15', 'node18'],
})
```
## Supported Targets
### ECMAScript Versions
- `es2015`, `es2016`, `es2017`, `es2018`, `es2019`, `es2020`, `es2021`, `es2022`, `es2023`, `esnext`
### Browser Versions
- `chrome100`, `safari18`, `firefox110`, `edge100`, etc.
### Node.js Versions
- `node16`, `node18`, `node20`, `node20.18`, etc.
## Examples
### Modern Browsers
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm'],
target: ['chrome100', 'safari15', 'firefox100'],
})
```
### Node.js Library
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
target: 'node18',
})
```
### Legacy Support
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm'],
target: 'es2015', // Maximum compatibility
})
```
### Per-Format Targets
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: {
esm: {
target: 'es2020',
},
cjs: {
target: 'node16',
},
},
})
```
## Decorators
### Legacy Decorators (Stage 2)
Enable in `tsconfig.json`:
```json
{
"compilerOptions": {
"experimentalDecorators": true
}
}
```
### Stage 3 Decorators
**Not currently supported** by tsdown/Rolldown/Oxc.
See [oxc issue #9170](https://github.com/oxc-project/oxc/issues/9170).
## Common Patterns
### Universal Library
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
target: 'es2020', // Wide compatibility
})
```
### Modern-Only Library
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm'],
target: false, // No transformations
})
```
### Browser Component
```ts
export default defineConfig({
entry: ['src/index.tsx'],
format: ['esm'],
target: ['chrome100', 'safari15', 'firefox100'],
platform: 'browser',
})
```
## Tips
1. **Let tsdown auto-detect** from package.json when possible
2. **Use `false`** for modern-only builds
3. **Specify multiple targets** for broader compatibility
4. **Use legacy decorators** with `experimentalDecorators`
6. **Test output** in target environments
## Related Options
- [Platform](option-platform.md) - Runtime environment
- [Output Format](option-output-format.md) - Module formats
- [Minification](option-minification.md) - Code optimization

View File

@@ -0,0 +1,335 @@
# Tree Shaking
Remove unused code from bundles.
## Overview
Tree shaking eliminates dead code (unused exports) from your final bundle, reducing size and improving performance.
**Default:** Enabled
## Basic Usage
### CLI
```bash
# Tree shaking enabled (default)
tsdown
# Disable tree shaking
tsdown --no-treeshake
```
### Config File
```ts
export default defineConfig({
entry: ['src/index.ts'],
treeshake: true, // Default
})
```
## How It Works
### With Tree Shaking
**Source:**
```ts
// src/util.ts
export function unused() {
console.log("I'm unused")
}
export function hello(x: number) {
console.log('Hello World', x)
}
// src/index.ts
import { hello } from './util'
hello(1)
```
**Output:**
```js
// dist/index.mjs
function hello(x) {
console.log('Hello World', x)
}
hello(1)
```
`unused()` function is removed because it's never imported.
### Without Tree Shaking
**Output:**
```js
// dist/index.mjs
function unused() {
console.log("I'm unused")
}
function hello(x) {
console.log('Hello World', x)
}
hello(1)
```
All code is included, even if unused.
## Advanced Configuration
### Enable (Default)
```ts
export default defineConfig({
treeshake: true,
})
```
Uses Rolldown's default tree shaking.
### Custom Options
```ts
export default defineConfig({
treeshake: {
moduleSideEffects: false,
propertyReadSideEffects: false,
unknownGlobalSideEffects: false,
},
})
```
See [Rolldown docs](https://rolldown.rs/reference/config-options#treeshake) for all options.
### Disable
```ts
export default defineConfig({
treeshake: false,
})
```
## Side Effects
### Package.json sideEffects
Declare side effects in your package:
```json
{
"sideEffects": false
}
```
Or specify files with side effects:
```json
{
"sideEffects": ["*.css", "src/polyfills.ts"]
}
```
### Module Side Effects
```ts
export default defineConfig({
treeshake: {
moduleSideEffects: (id) => {
// Preserve side effects for polyfills
return id.includes('polyfill')
},
},
})
```
## Common Patterns
### Production Build
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
treeshake: true,
minify: true,
})
```
### Development Build
```ts
export default defineConfig((options) => ({
entry: ['src/index.ts'],
treeshake: !options.watch, // Disable in dev
}))
```
### Library with Side Effects
```ts
export default defineConfig({
entry: ['src/index.ts'],
treeshake: {
moduleSideEffects: (id) => {
return (
id.includes('.css') ||
id.includes('polyfill') ||
id.includes('side-effect')
)
},
},
})
```
### Utilities Library
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm'],
treeshake: true,
dts: true,
})
```
Users can import only what they need:
```ts
import { onlyWhatINeed } from 'my-utils'
```
## Benefits
### Smaller Bundles
- Only includes imported code
- Removes unused functions, classes, variables
- Reduces download size
### Better Performance
- Less code to parse
- Faster execution
- Improved loading times
### Cleaner Output
- No dead code in production
- Easier to debug
- Better maintainability
## When to Disable
### Debugging
During development to see all code:
```ts
export default defineConfig((options) => ({
treeshake: !options.watch,
}))
```
### Side Effect Code
Code with global side effects:
```ts
// This has side effects
window.myGlobal = {}
export function setup() {
// ...
}
```
Disable tree shaking or mark side effects:
```json
{
"sideEffects": true
}
```
### Testing
Include all code for coverage:
```ts
export default defineConfig({
treeshake: false,
})
```
## Tips
1. **Leave enabled** for production builds
2. **Mark side effects** in package.json
3. **Use with minification** for best results
4. **Test tree shaking** - verify unused code is removed
5. **Disable for debugging** if needed
6. **Pure functions** are easier to tree shake
## Troubleshooting
### Code Still Included
- Check for side effects
- Verify imports are ES modules
- Ensure code is actually unused
- Check `sideEffects` in package.json
### Missing Code at Runtime
- Code has side effects but marked as none
- Set `sideEffects: true` or list specific files
### Unexpected Behavior
- Module has side effects not declared
- Try disabling tree shaking to isolate issue
## Examples
### Pure Utility Functions
```ts
// utils.ts - perfect for tree shaking
export function add(a, b) {
return a + b
}
export function multiply(a, b) {
return a * b
}
// Only 'add' imported = only 'add' bundled
import { add } from './utils'
```
### With Side Effects
```ts
// polyfill.ts - has side effects
if (!Array.prototype.at) {
Array.prototype.at = function(index) {
// polyfill implementation
}
}
export {} // Need to export something
```
```json
{
"sideEffects": ["src/polyfill.ts"]
}
```
## Related Options
- [Minification](option-minification.md) - Code compression
- [Target](option-target.md) - Syntax transformations
- [Dependencies](option-dependencies.md) - External packages
- [Output Format](option-output-format.md) - Module formats

View File

@@ -0,0 +1,309 @@
# Unbundle Mode
Preserve source directory structure in output.
## Overview
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.
## Basic Usage
### CLI
```bash
tsdown --unbundle
```
### Config File
```ts
export default defineConfig({
entry: ['src/**/*.ts', '!**/*.test.ts'],
unbundle: true,
})
```
## How It Works
### Source Structure
```
src/
├── index.ts
├── utils/
│ ├── helper.ts
│ └── format.ts
└── components/
└── button.ts
```
### With Unbundle
**Config:**
```ts
export default defineConfig({
entry: ['src/index.ts'],
unbundle: true,
})
```
**Output:**
```
dist/
├── index.mjs
├── utils/
│ ├── helper.mjs
│ └── format.mjs
└── components/
└── button.mjs
```
All imported files are output individually, preserving structure.
### Without Unbundle (Default)
**Output:**
```
dist/
└── index.mjs (all code bundled together)
```
## When to Use
### Use Unbundle When:
✅ 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
### Use Standard Bundling When:
❌ Single entry point application
❌ Want to optimize bundle size
❌ Need aggressive tree shaking
❌ Creating IIFE/UMD bundles
❌ Deploying to browsers directly
## Common Patterns
### Utility Library
```ts
export default defineConfig({
entry: ['src/**/*.ts', '!**/*.test.ts'],
format: ['esm', 'cjs'],
unbundle: true,
dts: true,
})
```
**Benefits:**
- Users import only what they need
- Tree shaking still works at user's build
- Clear module boundaries
**Usage:**
```ts
// Users can import specific utilities
import { helper } from 'my-lib/utils/helper'
import { Button } from 'my-lib/components/button'
```
### Monorepo Shared Package
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm'],
unbundle: true,
outDir: 'dist',
})
```
### TypeScript Compilation Only
```ts
export default defineConfig({
entry: ['src/**/*.ts'],
format: ['esm'],
unbundle: true,
minify: false,
treeshake: false,
dts: true,
})
```
Pure TypeScript to JavaScript transformation.
### Development Mode
```ts
export default defineConfig((options) => ({
entry: ['src/**/*.ts'],
unbundle: options.watch, // Unbundle in dev only
minify: !options.watch,
}))
```
Fast rebuilds during development, optimized for production.
## With Entry Patterns
### Include/Exclude
```ts
export default defineConfig({
entry: [
'src/**/*.ts',
'!**/*.test.ts',
'!**/*.spec.ts',
'!**/fixtures/**',
],
unbundle: true,
})
```
### Multiple Entry Points
```ts
export default defineConfig({
entry: {
index: 'src/index.ts',
cli: 'src/cli.ts',
},
unbundle: true,
})
```
Both entry files and all imports preserved.
## Output Control
### Custom Extension
```ts
export default defineConfig({
entry: ['src/**/*.ts'],
unbundle: true,
outExtensions: () => ({ js: '.js' }),
})
```
### Preserve Directory
```ts
export default defineConfig({
entry: ['src/**/*.ts'],
unbundle: true,
outDir: 'lib',
})
```
**Output:**
```
lib/
├── index.js
├── utils/
│ └── helper.js
└── components/
└── button.js
```
## Package.json Setup
```json
{
"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.
## Comparison
| 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 |
## Performance
### Build Speed
Unbundle is typically faster:
- No bundling overhead
- Parallel file processing
- Incremental builds possible
### Bundle Size
Unbundle produces larger output:
- Each file has its own overhead
- No cross-module optimizations
- User's bundler handles final optimization
## Tips
1. **Use with glob patterns** for multiple files
2. **Enable in development** for faster rebuilds
3. **Let users bundle** for production optimization
4. **Preserve structure** for utilities/components
5. **Combine with DTS** for type definitions
6. **Use with monorepos** for shared code
## Troubleshooting
### Too Many Files
- Adjust entry patterns
- Exclude unnecessary files
- Use specific entry points
### Missing Files
- Check entry patterns
- Verify files are imported
- Look for excluded patterns
### Import Paths Wrong
- Check relative paths
- Verify output structure
- Update package.json exports
## CLI Examples
```bash
# Enable unbundle
tsdown --unbundle
# With specific entry
tsdown src/**/*.ts --unbundle
# With other options
tsdown --unbundle --format esm --dts
```
## Related Options
- [Entry](option-entry.md) - Entry patterns
- [Output Directory](option-output-directory.md) - Output location
- [Output Format](option-output-format.md) - Module formats
- [DTS](option-dts.md) - Type declarations

View File

@@ -0,0 +1,261 @@
# Watch Mode
Automatically rebuild when files change.
## Overview
Watch mode monitors your source files and rebuilds automatically on changes, streamlining the development workflow.
## Basic Usage
### CLI
```bash
# Watch all project files
tsdown --watch
# Or use short flag
tsdown -w
# Watch specific directory
tsdown --watch ./src
# Watch specific file
tsdown --watch ./src/index.ts
```
### Config File
```ts
export default defineConfig({
entry: ['src/index.ts'],
watch: true,
})
```
## Watch Options
### Ignore Paths
Ignore specific paths in watch mode:
```bash
tsdown --watch --ignore-watch test --ignore-watch '**/*.test.ts'
```
```ts
export default defineConfig({
entry: ['src/index.ts'],
watch: {
exclude: ['test/**', '**/*.test.ts'],
},
})
```
### On Success Command
Run command after successful build:
```bash
tsdown --watch --on-success "echo Build complete!"
tsdown --watch --on-success "node dist/index.mjs"
```
```ts
export default defineConfig({
entry: ['src/index.ts'],
watch: true,
onSuccess: 'node dist/index.mjs',
})
```
## Watch Behavior
### Default Watch Targets
By default, tsdown watches:
- All entry files
- All imported files
- Config file (triggers restart)
### File Change Handling
- **Source files** - Incremental rebuild
- **Config file** - Full restart with cache clear
- **Dependencies** - Rebuild if imported
### Keyboard Shortcuts
During watch mode:
- `r` - Manual rebuild
- `q` - Quit watch mode
## Common Patterns
### Development Mode
```ts
export default defineConfig((options) => ({
entry: ['src/index.ts'],
format: ['esm'],
watch: options.watch,
sourcemap: options.watch,
minify: !options.watch,
}))
```
### With Post-Build Script
```ts
export default defineConfig({
entry: ['src/index.ts'],
watch: true,
onSuccess: 'npm run test',
})
```
### Multiple Entry Points
```ts
export default defineConfig({
entry: {
main: 'src/index.ts',
cli: 'src/cli.ts',
},
watch: true,
clean: false, // Don't clean on each rebuild
})
```
### Test Runner Integration
```bash
# Watch and run tests on change
tsdown --watch --on-success "vitest run"
# Watch and start dev server
tsdown --watch --on-success "node dist/server.mjs"
```
### Monorepo Package
```ts
export default defineConfig({
workspace: 'packages/*',
entry: ['src/index.ts'],
watch: true,
watch: {
exclude: ['**/test/**', '**/*.spec.ts'],
},
})
```
## Advanced Configuration
### Custom Watch Options
```ts
export default defineConfig({
entry: ['src/index.ts'],
watch: {
include: ['src/**'],
exclude: ['**/*.test.ts', '**/fixtures/**'],
skipWrite: false,
},
})
```
### Conditional Watch
```ts
export default defineConfig((options) => {
const isDev = options.watch
return {
entry: ['src/index.ts'],
format: ['esm'],
dts: !isDev, // Skip DTS in watch mode
sourcemap: isDev,
clean: !isDev,
}
})
```
## CLI Examples
```bash
# Basic watch
tsdown -w
# Watch with source maps
tsdown -w --sourcemap
# Watch without cleaning
tsdown -w --no-clean
# Watch and run on success
tsdown -w --on-success "npm test"
# Watch specific format
tsdown -w --format esm
# Watch with minification
tsdown -w --minify
# Watch and ignore test files
tsdown -w --ignore-watch '**/*.test.ts'
```
## Tips
1. **Use watch mode** for active development
2. **Skip DTS generation** in watch for faster rebuilds
3. **Disable clean** to avoid unnecessary file operations
4. **Use onSuccess** for post-build tasks
5. **Ignore test files** to avoid unnecessary rebuilds
6. **Use keyboard shortcuts** for manual control
## Troubleshooting
### Watch Not Detecting Changes
- Check file is in entry or imported chain
- Verify path is not in `exclude` patterns
- Ensure file system supports watching
### Too Many Rebuilds
Add ignore patterns:
```ts
export default defineConfig({
watch: {
exclude: [
'**/node_modules/**',
'**/.git/**',
'**/dist/**',
'**/*.test.ts',
],
},
})
```
### Slow Rebuilds
- Skip DTS in watch mode: `dts: !options.watch`
- Disable minification: `minify: false`
- Use smaller entry set during development
### Config Changes Not Applied
Config file changes trigger full restart automatically.
### Why Not Stub Mode?
tsdown does not support stub mode. Watch mode is the recommended alternative for rapid development, providing instant rebuilds without the drawbacks of stub mode.
## Related Options
- [On Success](reference-cli.md#on-success-command) - Post-build commands
- [Sourcemap](option-sourcemap.md) - Debug information
- [Clean](option-cleaning.md) - Output directory cleaning

View File

@@ -0,0 +1,320 @@
# React Support
Build React component libraries with tsdown.
## Overview
tsdown provides first-class support for React libraries. Rolldown natively supports JSX/TSX, so no additional plugins are required for basic React components.
## Quick Start
### Use Starter Template
```bash
# Basic React library
npx create-tsdown@latest -t react
# With React Compiler
npx create-tsdown@latest -t react-compiler
```
## Basic Configuration
### Minimal Setup
```ts
// tsdown.config.ts
export default defineConfig({
entry: ['./src/index.ts'],
format: ['esm', 'cjs'],
platform: 'neutral',
external: ['react', 'react-dom'],
dts: true,
})
```
### Component Example
```tsx
// src/MyButton.tsx
import React from 'react'
interface MyButtonProps {
type?: 'primary' | 'secondary'
onClick?: () => void
}
export const MyButton: React.FC<MyButtonProps> = ({ type = 'primary', onClick }) => {
return (
<button className={`btn btn-${type}`} onClick={onClick}>
Click me
</button>
)
}
```
```ts
// src/index.ts
export { MyButton } from './MyButton'
```
## JSX Transform
### Automatic (Default)
Modern JSX transform (React 17+):
```ts
export default defineConfig({
entry: ['src/index.tsx'],
// Automatic JSX is default
})
```
**Characteristics:**
- No `import React` needed
- Smaller bundle size
- React 17+ required
### Classic
Legacy JSX transform:
```ts
export default defineConfig({
entry: ['src/index.tsx'],
inputOptions: {
transform: {
jsx: 'react', // Classic transform
},
},
})
```
**Characteristics:**
- Requires `import React from 'react'`
- Compatible with older React versions
## React Compiler
React Compiler automatically optimizes React code at build time.
### Install Dependencies
```bash
pnpm add -D @rollup/plugin-babel babel-plugin-react-compiler
```
### Configure
```ts
import pluginBabel from '@rollup/plugin-babel'
export default defineConfig({
entry: ['src/index.tsx'],
format: ['esm', 'cjs'],
external: ['react', 'react-dom'],
plugins: [
pluginBabel({
babelHelpers: 'bundled',
parserOpts: {
sourceType: 'module',
plugins: ['jsx', 'typescript'],
},
plugins: ['babel-plugin-react-compiler'],
extensions: ['.js', '.jsx', '.ts', '.tsx'],
}),
],
dts: true,
})
```
## Common Patterns
### Component Library
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
platform: 'neutral',
external: [
'react',
'react-dom',
/^react\//, // react/jsx-runtime, etc.
],
dts: true,
clean: true,
})
```
### Multiple Components
```ts
export default defineConfig({
entry: {
index: 'src/index.ts',
Button: 'src/Button.tsx',
Input: 'src/Input.tsx',
Modal: 'src/Modal.tsx',
},
format: ['esm', 'cjs'],
external: ['react', 'react-dom'],
dts: true,
})
```
### Hooks Library
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
platform: 'neutral',
external: ['react'], // Only React needed
dts: true,
treeshake: true,
})
```
### Monorepo React Packages
```ts
export default defineConfig({
workspace: 'packages/*',
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
external: [
'react',
'react-dom',
/^@mycompany\//, // Other workspace packages
],
dts: true,
})
```
## TypeScript Configuration
### Recommended tsconfig.json
```json
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"jsx": "react-jsx", // or "react" for classic
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"strict": true,
"isolatedDeclarations": true, // Fast DTS generation
"skipLibCheck": true
},
"include": ["src"]
}
```
## Package.json Configuration
```json
{
"name": "my-react-library",
"version": "1.0.0",
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
}
},
"files": ["dist"],
"peerDependencies": {
"react": "^18.0.0",
"react-dom": "^18.0.0"
},
"devDependencies": {
"@types/react": "^18.0.0",
"@types/react-dom": "^18.0.0",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"tsdown": "^0.9.0",
"typescript": "^5.0.0"
}
}
```
## Advanced Patterns
### With Fast Refresh (Development)
```ts
import react from '@vitejs/plugin-react'
export default defineConfig((options) => ({
entry: ['src/index.ts'],
format: ['esm'],
external: ['react', 'react-dom'],
plugins: options.watch
? [
// @ts-expect-error Vite plugin
react({ fastRefresh: true }),
]
: [],
}))
```
## Tips
1. **Always externalize React** - Don't bundle React/ReactDOM
2. **Use automatic JSX** - Smaller bundles with React 17+
3. **Enable DTS generation** - TypeScript support essential
4. **Use platform: 'neutral'** - For maximum compatibility
5. **Add peer dependencies** - Let users provide React
6. **Enable tree shaking** - Reduce bundle size
7. **Use React Compiler** - Better runtime performance
## Troubleshooting
### React Hook Errors
Ensure React is externalized:
```ts
external: ['react', 'react-dom', /^react\//]
```
### Type Errors with JSX
Check `tsconfig.json`:
```json
{
"compilerOptions": {
"jsx": "react-jsx" // or "react"
}
}
```
### Duplicate React
Add to external patterns:
```ts
external: [
'react',
'react-dom',
'react/jsx-runtime',
'react/jsx-dev-runtime',
]
```
## Related
- [Plugins](advanced-plugins.md) - Extend functionality
- [Dependencies](option-dependencies.md) - External packages
- [DTS](option-dts.md) - Type declarations
- [Vue Recipe](recipe-vue.md) - Vue component libraries

View File

@@ -0,0 +1,371 @@
# Vue Support
Build Vue component libraries with tsdown.
## Overview
tsdown provides first-class support for Vue libraries through integration with `unplugin-vue` and `rolldown-plugin-dts` for type generation.
## Quick Start
### Use Starter Template
```bash
npx create-tsdown@latest -t vue
```
## Basic Configuration
### Install Dependencies
```bash
pnpm add -D unplugin-vue vue-tsc
```
### Minimal Setup
```ts
// tsdown.config.ts
import { defineConfig } from 'tsdown'
import Vue from 'unplugin-vue/rolldown'
export default defineConfig({
entry: ['./src/index.ts'],
format: ['esm', 'cjs'],
platform: 'neutral',
external: ['vue'],
plugins: [
Vue({ isProduction: true }),
],
dts: {
vue: true, // Enable Vue type generation
},
})
```
## How It Works
### unplugin-vue
Compiles `.vue` single-file components:
- Transforms template to render functions
- Handles scoped styles
- Processes script setup
### vue-tsc
Generates TypeScript declarations:
- Type-checks Vue components
- Creates `.d.ts` files
- Preserves component props types
- Exports component types
## Component Example
### Single File Component
```vue
<!-- src/Button.vue -->
<script setup lang="ts">
interface Props {
type?: 'primary' | 'secondary'
disabled?: boolean
}
defineProps<Props>()
defineEmits<{
click: []
}>()
</script>
<template>
<button
:class="['btn', `btn-${type}`]"
:disabled="disabled"
@click="$emit('click')"
>
<slot />
</button>
</template>
<style scoped>
.btn {
padding: 8px 16px;
border-radius: 4px;
}
.btn-primary {
background: blue;
color: white;
}
</style>
```
### Export Components
```ts
// src/index.ts
export { default as Button } from './Button.vue'
export { default as Input } from './Input.vue'
export { default as Modal } from './Modal.vue'
// Re-export types
export type { ButtonProps } from './Button.vue'
```
## Common Patterns
### Component Library
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
platform: 'neutral',
external: ['vue'],
plugins: [
Vue({
isProduction: true,
style: {
trim: true,
},
}),
],
dts: {
vue: true,
},
clean: true,
})
```
### Multiple Components
```ts
export default defineConfig({
entry: {
index: 'src/index.ts',
Button: 'src/Button.vue',
Input: 'src/Input.vue',
Modal: 'src/Modal.vue',
},
format: ['esm', 'cjs'],
external: ['vue'],
plugins: [Vue({ isProduction: true })],
dts: { vue: true },
})
```
### With Composition Utilities
```ts
// src/composables/useCounter.ts
import { ref } from 'vue'
export function useCounter(initial = 0) {
const count = ref(initial)
const increment = () => count.value++
const decrement = () => count.value--
return { count, increment, decrement }
}
```
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
external: ['vue'],
plugins: [Vue({ isProduction: true })],
dts: { vue: true },
})
```
### TypeScript Configuration
```json
// tsconfig.json
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"jsx": "preserve",
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"strict": true,
"isolatedDeclarations": true,
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
}
```
### Package.json Configuration
```json
{
"name": "my-vue-library",
"version": "1.0.0",
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
},
},
"files": ["dist"],
"peerDependencies": {
"vue": "^3.0.0"
},
"devDependencies": {
"tsdown": "^0.9.0",
"typescript": "^5.0.0",
"unplugin-vue": "^5.0.0",
"vue": "^3.4.0",
"vue-tsc": "^2.0.0"
}
}
```
## Advanced Patterns
### With Vite Plugins
Some Vite Vue plugins may work:
```ts
import Vue from 'unplugin-vue/rolldown'
import Components from 'unplugin-vue-components/rolldown'
export default defineConfig({
entry: ['src/index.ts'],
external: ['vue'],
plugins: [
Vue({ isProduction: true }),
Components({
dts: 'src/components.d.ts',
}),
],
dts: { vue: true },
})
```
### JSX Support
```ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
external: ['vue'],
plugins: [
Vue({
isProduction: true,
script: {
propsDestructure: true,
},
}),
],
inputOptions: {
transform: {
jsx: 'automatic',
jsxImportSource: 'vue',
},
},
dts: { vue: true },
})
```
### Monorepo Vue Packages
```ts
export default defineConfig({
workspace: 'packages/*',
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
external: ['vue', /^@mycompany\//],
plugins: [Vue({ isProduction: true })],
dts: { vue: true },
})
```
## Plugin Options
### unplugin-vue Options
```ts
Vue({
isProduction: true,
script: {
defineModel: true,
propsDestructure: true,
},
style: {
trim: true,
},
template: {
compilerOptions: {
isCustomElement: (tag) => tag.startsWith('custom-'),
},
},
})
```
## Tips
1. **Always externalize Vue** - Don't bundle Vue itself
2. **Enable vue: true in dts** - For proper type generation
3. **Use platform: 'neutral'** - Maximum compatibility
4. **Install vue-tsc** - Required for type generation
5. **Set isProduction: true** - Optimize for production
6. **Add peer dependency** - Vue as peer dependency
## Troubleshooting
### Type Generation Fails
Ensure vue-tsc is installed:
```bash
pnpm add -D vue-tsc
```
Enable in config:
```ts
dts: { vue: true }
```
### Component Types Missing
Check TypeScript config:
```json
{
"compilerOptions": {
"jsx": "preserve",
"moduleResolution": "bundler"
}
}
```
### Vue Not Externalized
Add to external:
```ts
external: ['vue']
```
### SFC Compilation Errors
Check unplugin-vue version:
```bash
pnpm add -D unplugin-vue@latest
```
## Related
- [Plugins](advanced-plugins.md) - Plugin system
- [Dependencies](option-dependencies.md) - External packages
- [DTS](option-dts.md) - Type declarations
- [React Recipe](recipe-react.md) - React component libraries

View File

@@ -0,0 +1,125 @@
# WASM Support
Bundle WebAssembly modules in your TypeScript/JavaScript project.
## Overview
tsdown supports WASM through [`rolldown-plugin-wasm`](https://github.com/sxzz/rolldown-plugin-wasm), enabling direct `.wasm` imports with synchronous and asynchronous instantiation.
## Setup
### Install
```bash
pnpm add -D rolldown-plugin-wasm
```
### Configure
```ts
import { wasm } from 'rolldown-plugin-wasm'
import { defineConfig } from 'tsdown'
export default defineConfig({
entry: ['./src/index.ts'],
plugins: [wasm()],
})
```
### TypeScript Support
Add type declarations to `tsconfig.json`:
```jsonc
{
"compilerOptions": {
"types": ["rolldown-plugin-wasm/types"]
}
}
```
## Importing WASM Modules
### Direct Import
```ts
import { add } from './add.wasm'
add(1, 2)
```
### Async Init
Use `?init` query for async initialization:
```ts
import init from './add.wasm?init'
const instance = await init(imports) // imports optional
instance.exports.add(1, 2)
```
### Sync Init
Use `?init&sync` query for synchronous initialization:
```ts
import initSync from './add.wasm?init&sync'
const instance = initSync(imports) // imports optional
instance.exports.add(1, 2)
```
## wasm-bindgen Support
### Target `bundler` (Recommended)
```ts
import { add } from 'some-pkg'
add(1, 2)
```
### Target `web` (Node.js)
```ts
import { readFile } from 'node:fs/promises'
import init, { add } from 'some-pkg'
import wasmUrl from 'some-pkg/add_bg.wasm?url'
await init({
module_or_path: readFile(new URL(wasmUrl, import.meta.url)),
})
add(1, 2)
```
### Target `web` (Browser)
```ts
import init, { add } from 'some-pkg/add.js'
import wasmUrl from 'some-pkg/add_bg.wasm?url'
await init({ module_or_path: wasmUrl })
add(1, 2)
```
`nodejs` and `no-modules` wasm-bindgen targets are not supported.
## Plugin Options
```ts
wasm({
maxFileSize: 14 * 1024, // Max size for inline (default: 14KB)
fileName: '[hash][extname]', // Output file name pattern
publicPath: '', // Prefix for non-inlined file paths
targetEnv: 'auto', // 'auto' | 'auto-inline' | 'browser' | 'node'
})
```
| Option | Default | Description |
|--------|---------|-------------|
| `maxFileSize` | `14 * 1024` | Max file size for inlining. Set to `0` to always copy. |
| `fileName` | `'[hash][extname]'` | Pattern for emitted WASM files |
| `publicPath` | — | Prefix for non-inlined WASM file paths |
| `targetEnv` | `'auto'` | `'auto'` detects at runtime; `'browser'` omits Node builtins; `'node'` omits fetch |
## Related Options
- [Plugins](advanced-plugins.md) - Plugin system overview
- [Platform](option-platform.md) - Target platform configuration

View File

@@ -0,0 +1,395 @@
# CLI Reference
Complete reference for tsdown command-line interface.
## Overview
All CLI flags can also be set in the config file. CLI flags override config file options.
## Flag Patterns
CLI flag mapping rules:
- `--foo` sets `foo: true`
- `--no-foo` sets `foo: false`
- `--foo.bar` sets `foo: { bar: true }`
- `--format esm --format cjs` sets `format: ['esm', 'cjs']`
CLI flags support both camelCase and kebab-case. For example, `--outDir` and `--out-dir` are equivalent.
## Basic Commands
### Build
```bash
# Build with default config
tsdown
# Build specific files
tsdown src/index.ts src/cli.ts
# Build with watch mode
tsdown --watch
```
## Configuration
### `--config, -c <filename>`
Specify custom config file:
```bash
tsdown --config build.config.ts
tsdown -c custom-config.js
```
### `--no-config`
Disable config file loading:
```bash
tsdown --no-config src/index.ts
```
### `--config-loader <loader>`
Choose config loader (`auto`, `native`, `unrun`):
```bash
tsdown --config-loader unrun
```
### `--tsconfig <file>`
Specify TypeScript config file:
```bash
tsdown --tsconfig tsconfig.build.json
```
## Entry Points
### `[...files]`
Specify entry files as arguments:
```bash
tsdown src/index.ts src/utils.ts
```
## Output Options
### `--format <format>`
Output format (`esm`, `cjs`, `iife`, `umd`):
```bash
tsdown --format esm
tsdown --format esm --format cjs
```
### `--out-dir, -d <dir>`
Output directory:
```bash
tsdown --out-dir lib
tsdown -d dist
```
### `--dts`
Generate TypeScript declarations:
```bash
tsdown --dts
```
### `--clean`
Clean output directory before build:
```bash
tsdown --clean
```
## Build Options
### `--target <target>`
JavaScript target version:
```bash
tsdown --target es2020
tsdown --target node18
tsdown --target chrome100
tsdown --no-target # Disable transformations
```
### `--platform <platform>`
Target platform (`node`, `browser`, `neutral`):
```bash
tsdown --platform node
tsdown --platform browser
```
### `--minify`
Enable minification:
```bash
tsdown --minify
tsdown --no-minify
```
### `--sourcemap`
Generate source maps:
```bash
tsdown --sourcemap
tsdown --sourcemap inline
```
### `--treeshake`
Enable/disable tree shaking:
```bash
tsdown --treeshake
tsdown --no-treeshake
```
## Dependencies
### `--external <module>`
Mark module as external (not bundled):
```bash
tsdown --external react --external react-dom
```
### `--shims`
Add ESM/CJS compatibility shims:
```bash
tsdown --shims
```
## Development
### `--watch, -w [path]`
Enable watch mode:
```bash
tsdown --watch
tsdown -w
tsdown --watch src # Watch specific directory
```
### `--ignore-watch <path>`
Ignore paths in watch mode:
```bash
tsdown --watch --ignore-watch test
```
### `--on-success <command>`
Run command after successful build:
```bash
tsdown --watch --on-success "echo Build complete!"
```
## Environment Variables
### `--env.* <value>`
Set compile-time environment variables:
```bash
tsdown --env.NODE_ENV=production --env.API_URL=https://api.example.com
```
Access as `import.meta.env.*` or `process.env.*`.
### `--env-file <file>`
Load environment variables from file:
```bash
tsdown --env-file .env.production
```
### `--env-prefix <prefix>`
Filter environment variables by prefix (default: `TSDOWN_`):
```bash
tsdown --env-file .env --env-prefix APP_ --env-prefix TSDOWN_
```
## Assets
### `--copy <dir>`
Copy directory to output:
```bash
tsdown --copy public
tsdown --copy assets --copy static
```
## Package Management
### `--exports`
Auto-generate package.json exports field:
```bash
tsdown --exports
```
### `--publint`
Enable package validation:
```bash
tsdown --publint
```
### `--attw`
Enable "Are the types wrong" validation:
```bash
tsdown --attw
```
### `--unused`
Check for unused dependencies:
```bash
tsdown --unused
```
## Logging
### `--log-level <level>`
Set logging verbosity (`silent`, `error`, `warn`, `info`):
```bash
tsdown --log-level error
tsdown --log-level warn
```
### `--report` / `--no-report`
Enable/disable build report:
```bash
tsdown --no-report # Disable size report
tsdown --report # Enable (default)
```
### `--debug [feat]`
Show debug logs:
```bash
tsdown --debug
tsdown --debug rolldown # Debug specific feature
```
## Integration
### `--from-vite [vitest]`
Extend Vite or Vitest config:
```bash
tsdown --from-vite # Use vite.config.*
tsdown --from-vite vitest # Use vitest.config.*
```
## Common Usage Patterns
### Basic Build
```bash
tsdown
```
### Library (ESM + CJS + Types)
```bash
tsdown --format esm --format cjs --dts --clean
```
### Production Build
```bash
tsdown --minify --clean --no-report
```
### Development (Watch)
```bash
tsdown --watch --sourcemap
```
### Browser Bundle (IIFE)
```bash
tsdown --format iife --platform browser --minify
```
### Node.js CLI Tool
```bash
tsdown --format esm --platform node --shims
```
### Monorepo Package
```bash
tsdown --clean --dts --exports --publint
```
### With Environment Variables
```bash
tsdown --env-file .env.production --env.BUILD_TIME=$(date +%s)
```
### Copy Assets
```bash
tsdown --copy public --copy assets --clean
```
## Tips
1. **Use config file** for complex setups
2. **CLI flags override** config file options
3. **Chain multiple formats** for multi-target builds
4. **Use --clean** to avoid stale files
5. **Enable --dts** for TypeScript libraries
6. **Use --watch** during development
7. **Add --on-success** for post-build tasks
8. **Use --exports** to auto-generate package.json fields
## Related Documentation
- [Config File](option-config-file.md) - Configuration file options
- [Entry](option-entry.md) - Entry point configuration
- [Output Format](option-output-format.md) - Format options
- [Watch Mode](option-watch-mode.md) - Watch mode details