format: apply repo prettier (3.8.1) to the folded skills tree

963 markdown files reformatted with the repository's pinned prettier so
pnpm format:check covers the folded tree like every other repo file.

The formatter's embedded-language pass also normalized code fences
(TS semicolons, closed HTML tags in examples, lowercased CSS hex colors,
one renumbered list that skipped an index). Alphanumeric token deltas vs
the fold commit were audited file-by-file; all are formatter-equivalent
markup normalizations plus the four sanitized skills.
This commit is contained in:
fargo
2026-08-19 14:37:17 -05:00
parent d2eeb64433
commit 1a822493ba
962 changed files with 29594 additions and 27188 deletions
@@ -38,73 +38,73 @@ npx tsdown-migrate
## Basic Configuration
```ts
import { defineConfig } from 'tsdown'
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) |
| 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) |
| 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) |
| 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) |
| 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) |
| 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
@@ -116,7 +116,7 @@ export default defineConfig({
format: ['esm', 'cjs'],
dts: true,
clean: true,
})
});
```
### Multiple Entry Points
@@ -130,7 +130,7 @@ export default defineConfig({
},
format: ['esm', 'cjs'],
dts: true,
})
});
```
### Browser Library (IIFE/UMD)
@@ -142,7 +142,7 @@ export default defineConfig({
globalName: 'MyLib',
platform: 'browser',
minify: true,
})
});
```
### React Component Library
@@ -156,7 +156,7 @@ export default defineConfig({
plugins: [
// React Fast Refresh support
],
})
});
```
### Preserve Directory Structure
@@ -167,7 +167,7 @@ export default defineConfig({
unbundle: true, // Preserve file structure
format: ['esm'],
dts: true,
})
});
```
### CI-Aware Configuration
@@ -180,19 +180,19 @@ export default defineConfig({
failOnWarn: 'ci-only',
publint: 'ci-only',
attw: 'ci-only',
})
});
```
### WASM Support
```ts
import { wasm } from 'rolldown-plugin-wasm'
import { defineConfig } from 'tsdown'
import { wasm } from 'rolldown-plugin-wasm';
import { defineConfig } from 'tsdown';
export default defineConfig({
entry: ['src/index.ts'],
plugins: [wasm()],
})
});
```
### Advanced with Hooks
@@ -204,13 +204,13 @@ export default defineConfig({
dts: true,
hooks: {
'build:before': async (context) => {
console.log('Building...')
console.log('Building...');
},
'build:done': async (context) => {
console.log('Build complete!')
console.log('Build complete!');
},
},
})
});
```
## Configuration Features
@@ -231,7 +231,7 @@ export default defineConfig([
format: ['esm'],
platform: 'node',
},
])
]);
```
### Conditional Config
@@ -240,14 +240,14 @@ Use functions for dynamic configuration:
```ts
export default defineConfig((options) => {
const isDev = options.watch
const isDev = options.watch;
return {
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
minify: !isDev,
sourcemap: isDev,
}
})
};
});
```
### Workspace/Monorepo
@@ -260,7 +260,7 @@ export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
})
});
```
## CLI Quick Reference
@@ -292,43 +292,65 @@ tsdown --clean # Clean output directory
## Best Practices
1. **Always generate type declarations** for TypeScript libraries:
```ts
{ dts: true }
{
dts: true;
}
```
2. **Externalize dependencies** to avoid bundling unnecessary code:
```ts
{ external: [/^react/, /^@myorg\//] }
{
external: [/^react/, /^@myorg\//];
}
```
3. **Use tree shaking** for optimal bundle size:
```ts
{ treeshake: true }
{
treeshake: true;
}
```
4. **Enable minification** for production builds:
```ts
{ minify: true }
{
minify: true;
}
```
5. **Add shims** for better ESM/CJS compatibility:
```ts
{ shims: true } // Adds __dirname, __filename, etc.
{
shims: true;
} // Adds __dirname, __filename, etc.
```
6. **Auto-generate package.json exports**:
```ts
{ exports: true } // Creates proper exports field
{
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
{
unbundle: true;
} // Keep directory structure
```
9. **Validate packages** in CI before publishing:
@@ -5,10 +5,12 @@ 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)
@@ -31,6 +33,7 @@ This directory contains detailed reference documentation for the tsdown skill.
-`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
@@ -38,11 +41,13 @@ This directory contains detailed reference documentation for the tsdown skill.
-`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
@@ -63,6 +68,7 @@ These files can be added as needed:
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)
@@ -71,6 +77,7 @@ The tsdown skill now includes comprehensive coverage of:
- CLI reference
### ✅ Build Options
- Target environment configuration
- Platform selection
- Dependency management
@@ -81,6 +88,7 @@ The tsdown skill now includes comprehensive coverage of:
- Watch mode
### ✅ Advanced Features
- Plugins (Rolldown, Rollup, Unplugin)
- Lifecycle hooks
- ESM/CJS shims
@@ -93,6 +101,7 @@ The tsdown skill now includes comprehensive coverage of:
- CI environment detection and CI-aware options
### ✅ Framework & Runtime Support
- React with JSX/TSX
- React Compiler integration
- Vue with SFC support
@@ -100,6 +109,7 @@ The tsdown skill now includes comprehensive coverage of:
- WASM module bundling (rolldown-plugin-wasm)
### ✅ Migration
- Complete migration guide from tsup
- Compatibility notes
@@ -110,6 +120,7 @@ The skill is now ready for use with comprehensive coverage of core features. Add
## File Naming Convention
Files are prefixed by category:
- `guide-*` - Getting started guides and tutorials
- `option-*` - Configuration options
- `advanced-*` - Advanced topics (plugins, hooks, programmatic API)
@@ -10,11 +10,11 @@ tsdown uses the [`is-in-ci`](https://www.npmjs.com/package/is-in-ci) package to
Several options accept CI-aware string values:
| Value | Behavior |
|-------|----------|
| `true` | Always enabled |
| `false` | Always disabled |
| `'ci-only'` | Enabled only in CI, disabled locally |
| 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
@@ -36,10 +36,10 @@ These options accept CI-aware values:
```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)
})
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
@@ -56,7 +56,7 @@ export default defineConfig({
enabled: 'ci-only',
profile: 'node16',
},
})
});
```
### Config Function
@@ -67,7 +67,7 @@ The config function receives a `ci` boolean in its context:
export default defineConfig((_, { ci }) => ({
minify: ci,
sourcemap: !ci,
}))
}));
```
## Typical CI Configuration
@@ -80,7 +80,7 @@ export default defineConfig({
failOnWarn: 'ci-only',
publint: 'ci-only',
attw: 'ci-only',
})
});
```
## Related Options
@@ -17,13 +17,13 @@ export default defineConfig({
entry: ['src/index.ts'],
hooks: {
'build:prepare': async (context) => {
console.log('Build starting...')
console.log('Build starting...');
},
'build:done': async (context) => {
console.log('Build complete!')
console.log('Build complete!');
},
},
})
});
```
### Function Syntax
@@ -33,14 +33,14 @@ export default defineConfig({
entry: ['src/index.ts'],
hooks(hooks) {
hooks.hook('build:prepare', () => {
console.log('Preparing build...')
})
console.log('Preparing build...');
});
hooks.hook('build:before', (context) => {
console.log(`Building format: ${context.format}`)
})
console.log(`Building format: ${context.format}`);
});
},
})
});
```
## Available Hooks
@@ -52,6 +52,7 @@ Called before the build process starts.
**When:** Once per build session
**Context:**
```ts
{
options: ResolvedConfig,
@@ -60,11 +61,13 @@ Called before the build process starts.
```
**Use cases:**
- Setup tasks
- Validation
- Environment preparation
**Example:**
```ts
hooks: {
'build:prepare': async (context) => {
@@ -81,6 +84,7 @@ Called before each Rolldown build.
**When:** Once per format (ESM, CJS, etc.)
**Context:**
```ts
{
options: ResolvedConfig,
@@ -90,11 +94,13 @@ Called before each Rolldown build.
```
**Use cases:**
- Modify build options per format
- Inject plugins dynamically
- Format-specific setup
**Example:**
```ts
hooks: {
'build:before': async (context) => {
@@ -115,6 +121,7 @@ Called after the build completes.
**When:** Once per build session
**Context:**
```ts
{
options: ResolvedConfig,
@@ -124,12 +131,14 @@ Called after the build completes.
```
**Use cases:**
- Post-processing
- Asset copying
- Notifications
- Deployment
**Example:**
```ts
hooks: {
'build:done': async (context) => {
@@ -152,14 +161,14 @@ hooks: {
export default defineConfig({
hooks: {
'build:prepare': () => {
console.log('🚀 Starting build...')
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`)
const size = context.chunks.reduce((sum, c) => sum + c.code.length, 0);
console.log(`✅ Build complete! Total size: ${size} bytes`);
},
},
})
});
```
### Conditional Plugin Injection
@@ -170,26 +179,26 @@ export default defineConfig({
hooks.hook('build:before', (context) => {
// Add minification only for production
if (process.env.NODE_ENV === 'production') {
context.buildOptions.plugins.push(minifyPlugin())
context.buildOptions.plugins.push(minifyPlugin());
}
})
});
},
})
});
```
### Custom File Copy
```ts
import { copyFile } from 'fs/promises'
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`)
await copyFile('README.md', `${context.options.outDir}/README.md`);
},
},
})
});
```
### Build Metrics
@@ -198,19 +207,19 @@ export default defineConfig({
export default defineConfig({
hooks: {
'build:prepare': (context) => {
context.startTime = Date.now()
context.startTime = Date.now();
},
'build:done': (context) => {
const duration = Date.now() - context.startTime
console.log(`Build took ${duration}ms`)
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`)
})
console.log(`${chunk.fileName}: ${chunk.code.length} bytes`);
});
},
},
})
});
```
### Format-Specific Logic
@@ -220,18 +229,18 @@ export default defineConfig({
format: ['esm', 'cjs', 'iife'],
hooks: {
'build:before': (context) => {
const format = context.buildOptions.format
const format = context.buildOptions.format;
if (format === 'iife') {
// Browser-specific setup
context.buildOptions.globalName = 'MyLib'
context.buildOptions.globalName = 'MyLib';
} else if (format === 'cjs') {
// Node-specific setup
context.buildOptions.platform = 'node'
context.buildOptions.platform = 'node';
}
},
},
})
});
```
### Deployment Hook
@@ -241,12 +250,12 @@ export default defineConfig({
hooks: {
'build:done': async (context) => {
if (process.env.DEPLOY === 'true') {
console.log('Deploying to CDN...')
await deployToCDN(context.options.outDir)
console.log('Deploying to CDN...');
await deployToCDN(context.options.outDir);
}
},
},
})
});
```
## Advanced Usage
@@ -257,16 +266,16 @@ export default defineConfig({
export default defineConfig({
hooks(hooks) {
// Register multiple hooks
hooks.hook('build:prepare', setupEnvironment)
hooks.hook('build:prepare', validateConfig)
hooks.hook('build:prepare', setupEnvironment);
hooks.hook('build:prepare', validateConfig);
hooks.hook('build:before', injectPlugins)
hooks.hook('build:before', logFormat)
hooks.hook('build:before', injectPlugins);
hooks.hook('build:before', logFormat);
hooks.hook('build:done', generateManifest)
hooks.hook('build:done', notifyComplete)
hooks.hook('build:done', generateManifest);
hooks.hook('build:done', notifyComplete);
},
})
});
```
### Async Hooks
@@ -275,15 +284,15 @@ export default defineConfig({
export default defineConfig({
hooks: {
'build:prepare': async (context) => {
await fetchRemoteConfig()
await initializeDatabase()
await fetchRemoteConfig();
await initializeDatabase();
},
'build:done': async (context) => {
await uploadToS3(context.chunks)
await invalidateCDN()
await uploadToS3(context.chunks);
await invalidateCDN();
},
},
})
});
```
### Error Handling
@@ -293,14 +302,14 @@ export default defineConfig({
hooks: {
'build:done': async (context) => {
try {
await riskyOperation()
await riskyOperation();
} catch (error) {
console.error('Hook failed:', error)
console.error('Hook failed:', error);
// Don't throw - allow build to complete
}
},
},
})
});
```
## Hookable API
@@ -311,21 +320,21 @@ tsdown uses [hookable](https://github.com/unjs/hookable) for hooks. Additional m
export default defineConfig({
hooks(hooks) {
// Register hook
hooks.hook('build:done', handler)
hooks.hook('build:done', handler);
// Register hook once
hooks.hookOnce('build:prepare', handler)
hooks.hookOnce('build:prepare', handler);
// Remove hook
hooks.removeHook('build:done', handler)
hooks.removeHook('build:done', handler);
// Clear all hooks for event
hooks.removeHooks('build:done')
hooks.removeHooks('build:done');
// Call hooks manually
await hooks.callHook('build:done', context)
await hooks.callHook('build:done', context);
},
})
});
```
## Tips
@@ -13,11 +13,11 @@ tsdown, built on Rolldown, supports plugins from multiple ecosystems to extend a
Native plugins designed for Rolldown:
```ts
import RolldownPlugin from 'rolldown-plugin-something'
import RolldownPlugin from 'rolldown-plugin-something';
export default defineConfig({
plugins: [RolldownPlugin()],
})
});
```
**Compatibility:** ✅ Full support
@@ -27,16 +27,17 @@ export default defineConfig({
Universal plugins that work across bundlers:
```ts
import UnpluginPlugin from 'unplugin-something'
import UnpluginPlugin from 'unplugin-something';
export default defineConfig({
plugins: [UnpluginPlugin.rolldown()],
})
});
```
**Compatibility:** ✅ Most unplugin-* plugins work
**Compatibility:** ✅ Most unplugin-\* plugins work
**Examples:**
- `unplugin-vue-components`
- `unplugin-auto-import`
- `unplugin-icons`
@@ -46,11 +47,11 @@ export default defineConfig({
Most Rollup plugins work with tsdown:
```ts
import RollupPlugin from '@rollup/plugin-something'
import RollupPlugin from '@rollup/plugin-something';
export default defineConfig({
plugins: [RollupPlugin()],
})
});
```
**Compatibility:** ✅ High compatibility
@@ -58,7 +59,7 @@ export default defineConfig({
**Type Issues:** May cause TypeScript errors - use type casting:
```ts
import RollupPlugin from 'rollup-plugin-something'
import RollupPlugin from 'rollup-plugin-something';
export default defineConfig({
plugins: [
@@ -67,7 +68,7 @@ export default defineConfig({
// Or cast to any
RollupPlugin() as any,
],
})
});
```
### 4. Vite Plugins
@@ -75,14 +76,14 @@ export default defineConfig({
Some Vite plugins may work:
```ts
import VitePlugin from 'vite-plugin-something'
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
@@ -94,30 +95,26 @@ export default defineConfig({
### Basic Plugin Usage
```ts
import { defineConfig } from 'tsdown'
import SomePlugin from 'some-plugin'
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'
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(),
],
})
plugins: [PluginA(), PluginB({ option: true }), PluginC()],
});
```
### Conditional Plugins
@@ -125,12 +122,10 @@ export default defineConfig({
```ts
export default defineConfig((options) => ({
entry: ['src/index.ts'],
plugins: [
SomePlugin(),
options.watch && DevPlugin(),
!options.watch && ProdPlugin(),
].filter(Boolean),
}))
plugins: [SomePlugin(), options.watch && DevPlugin(), !options.watch && ProdPlugin()].filter(
Boolean,
),
}));
```
## Common Plugin Patterns
@@ -138,37 +133,37 @@ export default defineConfig((options) => ({
### JSON Import
```ts
import json from '@rollup/plugin-json'
import json from '@rollup/plugin-json';
export default defineConfig({
plugins: [json()],
})
});
```
### Node Resolve
```ts
import { nodeResolve } from '@rollup/plugin-node-resolve'
import { nodeResolve } from '@rollup/plugin-node-resolve';
export default defineConfig({
plugins: [nodeResolve()],
})
});
```
### CommonJS
```ts
import commonjs from '@rollup/plugin-commonjs'
import commonjs from '@rollup/plugin-commonjs';
export default defineConfig({
plugins: [commonjs()],
})
});
```
### Replace
```ts
import replace from '@rollup/plugin-replace'
import replace from '@rollup/plugin-replace';
export default defineConfig({
plugins: [
@@ -177,13 +172,13 @@ export default defineConfig({
__VERSION__: JSON.stringify('1.0.0'),
}),
],
})
});
```
### Auto Import
```ts
import AutoImport from 'unplugin-auto-import/rolldown'
import AutoImport from 'unplugin-auto-import/rolldown';
export default defineConfig({
plugins: [
@@ -192,13 +187,13 @@ export default defineConfig({
dts: 'src/auto-imports.d.ts',
}),
],
})
});
```
### Vue Components
```ts
import Components from 'unplugin-vue-components/rolldown'
import Components from 'unplugin-vue-components/rolldown';
export default defineConfig({
plugins: [
@@ -206,7 +201,7 @@ export default defineConfig({
dts: 'src/components.d.ts',
}),
],
})
});
```
## Framework-Specific Plugins
@@ -214,7 +209,7 @@ export default defineConfig({
### React
```ts
import react from '@vitejs/plugin-react'
import react from '@vitejs/plugin-react';
export default defineConfig({
entry: ['src/index.tsx'],
@@ -222,13 +217,13 @@ export default defineConfig({
// @ts-expect-error Vite plugin
react(),
],
})
});
```
### Vue
```ts
import vue from '@vitejs/plugin-vue'
import vue from '@vitejs/plugin-vue';
export default defineConfig({
entry: ['src/index.ts'],
@@ -236,13 +231,13 @@ export default defineConfig({
// @ts-expect-error Vite plugin
vue(),
],
})
});
```
### Solid
```ts
import solid from 'vite-plugin-solid'
import solid from 'vite-plugin-solid';
export default defineConfig({
entry: ['src/index.tsx'],
@@ -250,13 +245,13 @@ export default defineConfig({
// @ts-expect-error Vite plugin
solid(),
],
})
});
```
### Svelte
```ts
import { svelte } from '@sveltejs/vite-plugin-svelte'
import { svelte } from '@sveltejs/vite-plugin-svelte';
export default defineConfig({
entry: ['src/index.ts'],
@@ -264,7 +259,7 @@ export default defineConfig({
// @ts-expect-error Vite plugin
svelte(),
],
})
});
```
## Writing Custom Plugins
@@ -274,7 +269,7 @@ Follow Rolldown's plugin development guide:
### Basic Plugin Structure
```ts
import type { Plugin } from 'rolldown'
import type { Plugin } from 'rolldown';
function myPlugin(): Plugin {
return {
@@ -286,23 +281,23 @@ function myPlugin(): Plugin {
return {
code: transformCode(code),
map: null,
}
};
}
},
// Other hooks...
}
};
}
```
### Using Custom Plugin
```ts
import { myPlugin } from './my-plugin'
import { myPlugin } from './my-plugin';
export default defineConfig({
plugins: [myPlugin()],
})
});
```
## Plugin Configuration
@@ -318,11 +313,11 @@ Plugins run in the order they're defined:
```ts
export default defineConfig({
plugins: [
PluginA(), // Runs first
PluginB(), // Runs second
PluginC(), // Runs last
PluginA(), // Runs first
PluginB(), // Runs second
PluginC(), // Runs last
],
})
});
```
## Troubleshooting
@@ -339,7 +334,7 @@ plugins: [
// Option 2: as any
SomePlugin() as any,
]
];
```
### Plugin Not Working
@@ -11,19 +11,19 @@ tsdown can be imported and used programmatically in your Node.js scripts, custom
### Simple Build
```ts
import { build } from 'tsdown'
import { build } from 'tsdown';
await build({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
})
});
```
### With Options
```ts
import { build } from 'tsdown'
import { build } from 'tsdown';
await build({
entry: ['src/index.ts'],
@@ -33,7 +33,7 @@ await build({
minify: true,
sourcemap: true,
clean: true,
})
});
```
## API Reference
@@ -43,18 +43,21 @@ await build({
Main function to run a build.
```ts
import { build } from 'tsdown'
import { build } from 'tsdown';
await build(options)
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
@@ -62,7 +65,7 @@ await build(options)
All config file options are available:
```ts
import { build, defineConfig } from 'tsdown'
import { build, defineConfig } from 'tsdown';
const config = defineConfig({
entry: ['src/index.ts'],
@@ -71,15 +74,17 @@ const config = defineConfig({
minify: true,
sourcemap: true,
external: ['react', 'react-dom'],
plugins: [/* plugins */],
plugins: [
/* plugins */
],
hooks: {
'build:done': async () => {
console.log('Build complete!')
console.log('Build complete!');
},
},
})
});
await build(config)
await build(config);
```
See [Config Reference](option-config-file.md) for all options.
@@ -90,25 +95,26 @@ See [Config Reference](option-config-file.md) for all options.
```ts
// scripts/build.ts
import { build } from 'tsdown'
import { build } from 'tsdown';
async function main() {
console.log('Building library...')
console.log('Building library...');
await build({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
clean: true,
})
});
console.log('Build complete!')
console.log('Build complete!');
}
main().catch(console.error)
main().catch(console.error);
```
Run with:
```bash
tsx scripts/build.ts
```
@@ -116,7 +122,7 @@ tsx scripts/build.ts
### Multiple Builds
```ts
import { build } from 'tsdown'
import { build } from 'tsdown';
// Build main library
await build({
@@ -124,7 +130,7 @@ await build({
format: ['esm', 'cjs'],
outDir: 'dist',
dts: true,
})
});
// Build CLI tool
await build({
@@ -133,15 +139,15 @@ await build({
outDir: 'dist/bin',
platform: 'node',
shims: true,
})
});
```
### Conditional Build
```ts
import { build } from 'tsdown'
import { build } from 'tsdown';
const isDev = process.env.NODE_ENV === 'development'
const isDev = process.env.NODE_ENV === 'development';
await build({
entry: ['src/index.ts'],
@@ -149,64 +155,64 @@ await build({
minify: !isDev,
sourcemap: isDev,
clean: !isDev,
})
});
```
### With Error Handling
```ts
import { build } from 'tsdown'
import { build } from 'tsdown';
try {
await build({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
})
console.log('✅ Build successful')
});
console.log('✅ Build successful');
} catch (error) {
console.error('❌ Build failed:', error)
process.exit(1)
console.error('❌ Build failed:', error);
process.exit(1);
}
```
### Automated Workflow
```ts
import { build } from 'tsdown'
import { execSync } from 'child_process'
import { build } from 'tsdown';
import { execSync } from 'child_process';
async function release() {
// Clean
console.log('Cleaning...')
execSync('rm -rf dist')
console.log('Cleaning...');
execSync('rm -rf dist');
// Build
console.log('Building...')
console.log('Building...');
await build({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
minify: true,
})
});
// Test
console.log('Testing...')
execSync('npm test')
console.log('Testing...');
execSync('npm test');
// Publish
console.log('Publishing...')
execSync('npm publish')
console.log('Publishing...');
execSync('npm publish');
}
release().catch(console.error)
release().catch(console.error);
```
### Build with Post-Processing
```ts
import { build } from 'tsdown'
import { copyFileSync } from 'fs'
import { build } from 'tsdown';
import { copyFileSync } from 'fs';
await build({
entry: ['src/index.ts'],
@@ -215,12 +221,12 @@ await build({
hooks: {
'build:done': async () => {
// Copy additional files
copyFileSync('README.md', 'dist/README.md')
copyFileSync('LICENSE', 'dist/LICENSE')
console.log('Copied additional files')
copyFileSync('README.md', 'dist/README.md');
copyFileSync('LICENSE', 'dist/LICENSE');
console.log('Copied additional files');
},
},
})
});
```
## Watch Mode
@@ -229,12 +235,12 @@ Unfortunately, watch mode is not directly exposed in the programmatic API. Use t
```ts
// Use CLI for watch mode
import { spawn } from 'child_process'
import { spawn } from 'child_process';
spawn('tsdown', ['--watch'], {
stdio: 'inherit',
shell: true,
})
});
```
## Integration Examples
@@ -243,30 +249,30 @@ spawn('tsdown', ['--watch'], {
```ts
// gulpfile.js
import { build } from 'tsdown'
import gulp from 'gulp'
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'))
})
return gulp.watch('src/**/*.ts', gulp.series('build'));
});
```
### With Custom CLI
```ts
// scripts/cli.ts
import { build } from 'tsdown'
import { Command } from 'commander'
import { build } from 'tsdown';
import { Command } from 'commander';
const program = new Command()
const program = new Command();
program
.command('build')
@@ -277,19 +283,19 @@ program
format: ['esm', 'cjs'],
minify: options.prod,
sourcemap: !options.prod,
})
})
});
});
program.parse()
program.parse();
```
### With CI/CD
```ts
// .github/scripts/build.ts
import { build } from 'tsdown'
import { build } from 'tsdown';
const isCI = process.env.CI === 'true'
const isCI = process.env.CI === 'true';
await build({
entry: ['src/index.ts'],
@@ -297,7 +303,7 @@ await build({
dts: true,
minify: isCI,
clean: true,
})
});
// Upload to artifact storage
if (isCI) {
@@ -309,15 +315,15 @@ if (isCI) {
```ts
// scripts/build.ts
import { build, type UserConfig } from 'tsdown'
import { build, type UserConfig } from 'tsdown';
const config: UserConfig = {
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
}
};
await build(config)
await build(config);
```
## Tips
@@ -334,6 +340,7 @@ await build(config)
### Import Errors
Ensure tsdown is installed:
```bash
pnpm add -D tsdown
```
@@ -341,31 +348,38 @@ pnpm add -D tsdown
### Type Errors
Import types:
```ts
import type { UserConfig } from 'tsdown'
import type { UserConfig } from 'tsdown';
```
### Build Fails Silently
Add error handling:
```ts
try {
await build(config)
await build(config);
} catch (error) {
console.error(error)
process.exit(1)
console.error(error);
process.exit(1);
}
```
### Options Not Working
Check spelling and types:
```ts
// ✅ Correct
{ format: ['esm', 'cjs'] }
{
format: ['esm', 'cjs'];
}
// ❌ Wrong
{ formats: ['esm', 'cjs'] }
{
formats: ['esm', 'cjs'];
}
```
## Related
@@ -17,7 +17,7 @@ export default defineConfig({
inputOptions: {
cwd: './custom-directory',
},
})
});
```
### Using a Function
@@ -27,10 +27,10 @@ Dynamically modify options based on the output format:
```ts
export default defineConfig({
inputOptions(inputOptions, format) {
inputOptions.cwd = './custom-directory'
return inputOptions
inputOptions.cwd = './custom-directory';
return inputOptions;
},
})
});
```
## Output Options
@@ -42,7 +42,7 @@ export default defineConfig({
outputOptions: {
legalComments: 'inline',
},
})
});
```
### Using a Function
@@ -51,11 +51,11 @@ export default defineConfig({
export default defineConfig({
outputOptions(outputOptions, format) {
if (format === 'esm') {
outputOptions.legalComments = 'inline'
outputOptions.legalComments = 'inline';
}
return outputOptions
return outputOptions;
},
})
});
```
## Common Use Cases
@@ -68,7 +68,7 @@ export default defineConfig({
outputOptions: {
legalComments: 'inline',
},
})
});
```
### Custom Working Directory
@@ -79,7 +79,7 @@ export default defineConfig({
inputOptions: {
cwd: './packages/my-lib',
},
})
});
```
### Format-Specific Options
@@ -90,11 +90,11 @@ export default defineConfig({
format: ['esm', 'cjs'],
outputOptions(outputOptions, format) {
if (format === 'esm') {
outputOptions.legalComments = 'inline'
outputOptions.legalComments = 'inline';
}
return outputOptions
return outputOptions;
},
})
});
```
## When to Use
@@ -14,6 +14,7 @@ pnpm add -D typescript
```
**Requirements:**
- Node.js 20.19 or higher
- Experimental support for Deno and Bun
@@ -26,6 +27,7 @@ pnpm create tsdown@latest
```
Provides templates for:
- Pure TypeScript libraries
- React component libraries
- Vue component libraries
@@ -37,12 +39,12 @@ Provides templates for:
```ts
// src/index.ts
import { hello } from './hello.ts'
hello()
import { hello } from './hello.ts';
hello();
// src/hello.ts
export function hello() {
console.log('Hello tsdown!')
console.log('Hello tsdown!');
}
```
@@ -50,11 +52,11 @@ export function hello() {
```ts
// tsdown.config.ts
import { defineConfig } from 'tsdown'
import { defineConfig } from 'tsdown';
export default defineConfig({
entry: ['./src/index.ts'],
})
});
```
### 3. Run Build
@@ -117,7 +119,7 @@ export default defineConfig({
format: ['esm', 'cjs'],
dts: true,
clean: true,
})
});
```
### Browser Library (IIFE)
@@ -129,7 +131,7 @@ export default defineConfig({
globalName: 'MyLib',
platform: 'browser',
minify: true,
})
});
```
### Multiple Entry Points
@@ -143,7 +145,7 @@ export default defineConfig({
},
format: ['esm', 'cjs'],
dts: true,
})
});
```
## Using Plugins
@@ -151,12 +153,12 @@ export default defineConfig({
Add Rolldown, Rollup, or Unplugin plugins:
```ts
import SomePlugin from 'some-plugin'
import SomePlugin from 'some-plugin';
export default defineConfig({
entry: ['src/index.ts'],
plugins: [SomePlugin()],
})
});
```
## Watch Mode
@@ -35,12 +35,12 @@ npx tsdown-migrate packages/foo packages/bar
### 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 |
| 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
@@ -48,18 +48,18 @@ npx tsdown-migrate packages/foo packages/bar
```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)
})
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
})
workspace: 'packages/*', // Build all packages
});
```
## Migration Checklist
@@ -76,47 +76,52 @@ export default defineConfig({
### 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
format: ['esm', 'cjs'], // ESM now default
dts: true,
clean: true, // Now enabled by default
})
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": {
@@ -127,6 +132,7 @@ export default defineConfig({
```
**After (package.json):**
```json
{
"scripts": {
@@ -141,6 +147,7 @@ export default defineConfig({
### Supported tsup Features
Most tsup features are supported:
- ✅ Multiple entry points
- ✅ Multiple formats (ESM, CJS, IIFE, UMD)
- ✅ TypeScript declarations
@@ -174,6 +181,7 @@ Some tsup features are not yet available. Check [GitHub issues](https://github.c
### 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
@@ -20,8 +20,8 @@ cjsDefault?: boolean // default: true
export default defineConfig({
entry: ['src/index.ts'],
format: ['cjs'],
cjsDefault: true, // default behavior
})
cjsDefault: true, // default behavior
});
```
### Disabled
@@ -31,7 +31,7 @@ export default defineConfig({
entry: ['src/index.ts'],
format: ['cjs'],
cjsDefault: false,
})
});
```
## How It Works
@@ -41,27 +41,30 @@ export default defineConfig({
When your module has **only a single default export**, tsdown transforms:
**Source:**
```ts
// src/index.ts
export default function greet() {
console.log('Hello, world!')
console.log('Hello, world!');
}
```
**Generated CJS:**
```js
// dist/index.cjs
function greet() {
console.log('Hello, world!')
console.log('Hello, world!');
}
module.exports = greet
module.exports = greet;
```
**Generated Declaration:**
```ts
// dist/index.d.cts
declare function greet(): void
export = greet
declare function greet(): void;
export = greet;
```
This allows consumers to use `const greet = require('your-module')` directly.
@@ -73,9 +76,9 @@ The default export stays as `exports.default`:
```js
// dist/index.cjs
function greet() {
console.log('Hello, world!')
console.log('Hello, world!');
}
exports.default = greet
exports.default = greet;
```
Consumers need `require('your-module').default`.
@@ -23,8 +23,8 @@ tsdown --no-clean
```ts
export default defineConfig({
entry: ['src/index.ts'],
clean: true, // Default
})
clean: true, // Default
});
```
## Behavior
@@ -32,11 +32,13 @@ export default defineConfig({
### 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
@@ -48,10 +50,11 @@ 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
@@ -65,9 +68,9 @@ export default defineConfig({
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
clean: true, // Ensure clean output
clean: true, // Ensure clean output
minify: true,
})
});
```
### Development Mode
@@ -75,9 +78,9 @@ export default defineConfig({
```ts
export default defineConfig((options) => ({
entry: ['src/index.ts'],
clean: !options.watch, // Don't clean in watch mode
clean: !options.watch, // Don't clean in watch mode
sourcemap: options.watch,
}))
}));
```
### Multiple Builds
@@ -87,14 +90,14 @@ export default defineConfig([
{
entry: ['src/index.ts'],
outDir: 'dist',
clean: true, // Clean once
clean: true, // Clean once
},
{
entry: ['src/cli.ts'],
outDir: 'dist',
clean: false, // Don't clean, add to same dir
clean: false, // Don't clean, add to same dir
},
])
]);
```
### Monorepo Package
@@ -103,8 +106,8 @@ export default defineConfig([
export default defineConfig({
workspace: 'packages/*',
entry: ['src/index.ts'],
clean: true, // Clean each package's dist
})
clean: true, // Clean each package's dist
});
```
### Preserve Static Files
@@ -112,9 +115,9 @@ export default defineConfig({
```ts
export default defineConfig({
entry: ['src/index.ts'],
clean: false, // Keep manually added files
clean: false, // Keep manually added files
outDir: 'dist',
})
});
// Manually copy files first
// Then run tsdown --no-clean
@@ -125,18 +128,18 @@ export default defineConfig({
### Selective Cleaning
```ts
import { rmSync } from 'fs'
import { rmSync } from 'fs';
export default defineConfig({
clean: false, // Disable auto clean
clean: false, // Disable auto clean
hooks: {
'build:prepare': () => {
// Custom cleaning logic
rmSync('dist/*.js', { force: true })
rmSync('dist/*.js', { force: true });
// Keep other files
},
},
})
});
```
### Clean Specific Directories
@@ -146,14 +149,14 @@ export default defineConfig({
clean: false,
hooks: {
'build:prepare': async () => {
const { rm } = await import('fs/promises')
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 })
await rm('dist/esm', { recursive: true, force: true });
await rm('dist/cjs', { recursive: true, force: true });
// Keep dist/types
},
},
})
});
```
## Watch Mode Behavior
@@ -166,11 +169,12 @@ In watch mode, cleaning behavior is important:
export default defineConfig((options) => ({
entry: ['src/index.ts'],
watch: options.watch,
clean: !options.watch, // Only clean initial build
}))
clean: !options.watch, // Only clean initial build
}));
```
**Result:**
- First build: Clean
- Subsequent rebuilds: Incremental
@@ -179,8 +183,8 @@ export default defineConfig((options) => ({
```ts
export default defineConfig({
watch: true,
clean: true, // Clean every rebuild
})
clean: true, // Clean every rebuild
});
```
**Trade-off:** Slower rebuilds, but always fresh output.
@@ -244,9 +248,9 @@ tsdown --clean
export default defineConfig({
entry: ['src/index.ts'],
watch: true,
clean: false, // Faster rebuilds
clean: false, // Faster rebuilds
sourcemap: true,
})
});
```
### Multi-Stage Build
@@ -262,9 +266,9 @@ export default defineConfig([
{
entry: ['src/utils.ts'],
outDir: 'dist',
clean: false, // Add to same directory
clean: false, // Add to same directory
},
])
]);
```
## Related Options
@@ -9,6 +9,7 @@ tsdown searches for config files automatically in the current directory and pare
## Supported File Names
tsdown looks for these files (in order):
- `tsdown.config.ts`
- `tsdown.config.mts`
- `tsdown.config.cts`
@@ -25,14 +26,14 @@ tsdown looks for these files (in order):
```ts
// tsdown.config.ts
import { defineConfig } from 'tsdown'
import { defineConfig } from 'tsdown';
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
clean: true,
})
});
```
### JavaScript Config
@@ -43,7 +44,7 @@ export default {
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
}
};
```
### JSON Config
@@ -90,7 +91,7 @@ export default defineConfig([
globalName: 'MyLib',
minify: true,
},
])
]);
```
Each configuration runs as a separate build.
@@ -101,7 +102,7 @@ Use a function for conditional config:
```ts
export default defineConfig((options) => {
const isDev = options.watch
const isDev = options.watch;
return {
entry: ['src/index.ts'],
@@ -109,11 +110,12 @@ export default defineConfig((options) => {
minify: !isDev,
sourcemap: isDev,
clean: !isDev,
}
})
};
});
```
Available options:
- `watch` - Whether watch mode is enabled
- Other CLI flags passed to config
@@ -189,7 +191,7 @@ export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
})
});
```
Each package directory matching the glob pattern will be built with the same configuration.
@@ -214,7 +216,7 @@ export default defineConfig([
platform: 'browser',
globalName: 'MyLib',
},
])
]);
```
### Development vs Production
@@ -226,7 +228,7 @@ export default defineConfig((options) => ({
minify: !options.watch,
sourcemap: options.watch ? true : false,
clean: !options.watch,
}))
}));
```
### Monorepo Root Config
@@ -240,7 +242,7 @@ export default defineConfig({
dts: true,
clean: true,
// Shared config for all packages
})
});
```
### Per-Package Override
@@ -251,7 +253,7 @@ export default defineConfig({
entry: ['src/index.ts'],
format: ['esm'], // Override: only ESM
platform: 'browser', // Override: browser only
})
});
```
## Config Precedence
@@ -32,12 +32,12 @@ Mark dependencies as external (not bundled):
export default defineConfig({
entry: ['src/index.ts'],
external: [
'react', // Single package
'react', // Single package
'react-dom',
/^@myorg\//, // Regex pattern (all @myorg/* packages)
/^lodash/, // All lodash packages
/^@myorg\//, // Regex pattern (all @myorg/* packages)
/^lodash/, // All lodash packages
],
})
});
```
### `noExternal`
@@ -48,10 +48,10 @@ Force dependencies to be bundled:
export default defineConfig({
entry: ['src/index.ts'],
noExternal: [
'some-package', // Bundle this even if in dependencies
'some-package', // Bundle this even if in dependencies
'vendor-lib',
],
})
});
```
### `skipNodeModulesBundle`
@@ -62,7 +62,7 @@ Skip resolving and bundling ALL node_modules:
export default defineConfig({
entry: ['src/index.ts'],
skipNodeModulesBundle: true,
})
});
```
**Result:** No dependencies from node_modules are parsed or bundled.
@@ -78,10 +78,10 @@ export default defineConfig({
external: [
'react',
'react-dom',
/^react\//, // react/jsx-runtime, etc.
/^react\//, // react/jsx-runtime, etc.
],
dts: true,
})
});
```
### Utility Library with Shared Deps
@@ -93,7 +93,7 @@ export default defineConfig({
// Bundle lodash utilities
noExternal: ['lodash-es'],
dts: true,
})
});
```
### Monorepo Package
@@ -103,10 +103,10 @@ export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
external: [
/^@mycompany\//, // Don't bundle other workspace packages
/^@mycompany\//, // Don't bundle other workspace packages
],
dts: true,
})
});
```
### CLI Tool (Bundle Everything)
@@ -119,7 +119,7 @@ export default defineConfig({
// Bundle all dependencies for standalone CLI
noExternal: [/.*/],
shims: true,
})
});
```
### Library with Specific Externals
@@ -128,13 +128,9 @@ export default defineConfig({
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
external: [
'vue',
'@vue/runtime-core',
'@vue/reactivity',
],
external: ['vue', '@vue/runtime-core', '@vue/reactivity'],
dts: true,
})
});
```
## Declaration Files
@@ -149,12 +145,13 @@ Use TypeScript resolver for complex third-party types:
export default defineConfig({
entry: ['src/index.ts'],
dts: {
resolver: 'tsc', // Use TypeScript resolver instead of Oxc
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
@@ -184,7 +181,7 @@ tsdown --no-external some-package
// Don't bundle framework
export default defineConfig({
external: ['vue', 'react', 'solid-js', 'svelte'],
})
});
```
### Standalone App
@@ -194,7 +191,7 @@ export default defineConfig({
export default defineConfig({
noExternal: [/.*/],
skipNodeModulesBundle: false,
})
});
```
### Shared Library
@@ -202,9 +199,9 @@ export default defineConfig({
```ts
// Bundle only specific utils
export default defineConfig({
external: [/.*/], // External by default
external: [/.*/], // External by default
noExternal: ['tiny-utils'], // Except this one
})
});
```
### Monorepo Package
@@ -213,14 +210,14 @@ export default defineConfig({
// External workspace packages, bundle utilities
export default defineConfig({
external: [
/^@workspace\//, // Other workspace packages
/^@workspace\//, // Other workspace packages
'react',
'react-dom',
],
noExternal: [
'lodash-es', // Bundle utility libraries
'lodash-es', // Bundle utility libraries
],
})
});
```
## Troubleshooting
@@ -242,7 +239,7 @@ Or explicitly externalize:
```ts
export default defineConfig({
external: ['should-be-external'],
})
});
```
### Missing Dependency at Runtime
@@ -262,7 +259,7 @@ Or bundle it:
```ts
export default defineConfig({
noExternal: ['needed-package'],
})
});
```
### Type Resolution Errors
@@ -274,21 +271,24 @@ 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
@@ -7,6 +7,7 @@ Generate `.d.ts` type declaration files for your library.
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
@@ -14,6 +15,7 @@ tsdown uses [rolldown-plugin-dts](https://github.com/sxzz/rolldown-plugin-dts) t
### Auto-Enabled
DTS generation is **automatically enabled** if `package.json` contains:
- `types` field, or
- `typings` field
@@ -30,7 +32,7 @@ tsdown --dts
```ts
export default defineConfig({
dts: true,
})
});
```
## Performance
@@ -73,7 +75,7 @@ export default defineConfig({
dts: {
sourcemap: true,
},
})
});
```
## Advanced Options
@@ -89,7 +91,7 @@ export default defineConfig({
removeComments: false,
},
},
})
});
```
## Build Process
@@ -106,10 +108,11 @@ export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
})
});
```
Output:
- `dist/index.mjs`
- `dist/index.cjs`
- `dist/index.d.ts`
@@ -124,10 +127,11 @@ export default defineConfig({
},
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`
@@ -140,7 +144,7 @@ export default defineConfig({
dts: {
sourcemap: true, // Enable declaration maps
},
})
});
```
### Fast Build (Isolated Declarations)
@@ -162,7 +166,7 @@ export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true, // Will use fast oxc-transform
})
});
```
## Troubleshooting
@@ -196,7 +200,7 @@ export default defineConfig({
dts: {
vue: true,
},
})
});
```
### Oxc Transform
@@ -206,9 +210,9 @@ Control Oxc usage for declaration generation:
```ts
export default defineConfig({
dts: {
oxc: true, // Use oxc-transform (fast, requires isolatedDeclarations)
oxc: true, // Use oxc-transform (fast, requires isolatedDeclarations)
},
})
});
```
### Custom TSConfig
@@ -220,21 +224,21 @@ 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 |
| 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
@@ -28,7 +28,7 @@ tsdown 'src/*.ts'
```ts
export default defineConfig({
entry: 'src/index.ts',
})
});
```
#### Multiple Entries (Array)
@@ -36,7 +36,7 @@ export default defineConfig({
```ts
export default defineConfig({
entry: ['src/entry1.ts', 'src/entry2.ts'],
})
});
```
#### Named Entries (Object)
@@ -48,10 +48,11 @@ export default defineConfig({
utils: 'src/utils.ts',
cli: 'src/cli.ts',
},
})
});
```
Output files will match the keys:
- `dist/main.mjs`
- `dist/utils.mjs`
- `dist/cli.mjs`
@@ -65,7 +66,7 @@ Match multiple files dynamically using glob patterns:
```ts
export default defineConfig({
entry: 'src/**/*.ts',
})
});
```
### Exclude Test Files
@@ -73,7 +74,7 @@ export default defineConfig({
```ts
export default defineConfig({
entry: ['src/*.ts', '!src/*.test.ts'],
})
});
```
### Object Entries with Glob Patterns
@@ -86,7 +87,7 @@ export default defineConfig({
// Maps src/foo.ts → dist/lib/foo.js, src/bar.ts → dist/lib/bar.js
'lib/*': 'src/*.ts',
},
})
});
```
#### Negation Patterns in Object Entries
@@ -98,7 +99,7 @@ export default defineConfig({
entry: {
'hooks/*': ['src/hooks/*.ts', '!src/hooks/index.ts'],
},
})
});
```
Multiple positive and negation patterns:
@@ -113,7 +114,7 @@ export default defineConfig({
'!src/utils/internal.ts',
],
},
})
});
```
**Warning:** Multiple positive patterns in an array value must share the same base directory.
@@ -124,13 +125,8 @@ 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'] },
],
})
entry: ['src/*', '!src/foo.ts', { main: 'index.ts' }, { 'lib/*': ['src/*.ts', '!src/bar.ts'] }],
});
```
Object entries take precedence when output names conflict.
@@ -141,10 +137,10 @@ Use forward slashes `/` instead of backslashes `\` on Windows:
```ts
// ✅ Correct
entry: 'src/utils/*.ts'
entry: 'src/utils/*.ts';
// ❌ Wrong on Windows
entry: 'src\\utils\\*.ts'
entry: 'src\\utils\\*.ts';
```
## Common Patterns
@@ -156,7 +152,7 @@ export default defineConfig({
entry: 'src/index.ts',
format: ['esm', 'cjs'],
dts: true,
})
});
```
### Library with Multiple Exports
@@ -170,7 +166,7 @@ export default defineConfig({
},
format: ['esm', 'cjs'],
dts: true,
})
});
```
### CLI Tool
@@ -182,7 +178,7 @@ export default defineConfig({
},
format: ['esm'],
platform: 'node',
})
});
```
### Preserve Directory Structure
@@ -195,10 +191,11 @@ export default defineConfig({
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`
@@ -28,7 +28,7 @@ Checks that `package.json` fields (`exports`, `main`, `module`, `types`) match y
```ts
export default defineConfig({
publint: true,
})
});
```
### Configuration
@@ -38,7 +38,7 @@ export default defineConfig({
publint: {
level: 'error', // 'warning' | 'error' | 'suggestion'
},
})
});
```
### CLI
@@ -56,7 +56,7 @@ Verifies TypeScript declarations are correct across different module resolution
```ts
export default defineConfig({
attw: true,
})
});
```
### Configuration
@@ -64,39 +64,39 @@ export default defineConfig({
```ts
export default defineConfig({
attw: {
profile: 'node16', // 'strict' | 'node16' | 'esm-only'
level: 'error', // 'warn' | 'error'
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 |
| 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 |
| 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
@@ -116,7 +116,7 @@ export default defineConfig({
profile: 'node16',
level: 'error',
},
})
});
```
Both tools require a `package.json` in your project directory.
@@ -38,17 +38,17 @@ tsdown --log-level info
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) |
| 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
@@ -57,8 +57,8 @@ export default defineConfig({
```ts
export default defineConfig({
entry: ['src/index.ts'],
logLevel: 'error', // Only show errors in CI
})
logLevel: 'error', // Only show errors in CI
});
```
### Scripting
@@ -66,8 +66,8 @@ export default defineConfig({
```ts
export default defineConfig({
entry: ['src/index.ts'],
logLevel: 'silent', // No output for automation
})
logLevel: 'silent', // No output for automation
});
```
## Fail on Warnings
@@ -79,7 +79,7 @@ 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.
@@ -39,7 +39,7 @@ tsdown --no-minify
export default defineConfig({
entry: ['src/index.ts'],
minify: true,
})
});
```
### DCE-Only Mode
@@ -50,7 +50,7 @@ Remove dead code without full minification (keeps readable output):
export default defineConfig({
entry: ['src/index.ts'],
minify: 'dce-only',
})
});
```
## Example Output
@@ -59,21 +59,25 @@ export default defineConfig({
```js
// dist/index.mjs
const x = 1
const x = 1;
function hello(x$1) {
console.log('Hello World')
console.log(x$1)
console.log('Hello World');
console.log(x$1);
}
hello(x)
hello(x);
```
### With Minification
```js
// dist/index.mjs
const e=1;function t(e){console.log(`Hello World`),console.log(e)}t(e);
const e = 1;
function t(e) {
(console.log(`Hello World`), console.log(e));
}
t(e);
```
## Common Patterns
@@ -86,7 +90,7 @@ export default defineConfig({
format: ['esm', 'cjs'],
minify: true,
clean: true,
})
});
```
### Conditional Minification
@@ -95,8 +99,8 @@ export default defineConfig({
export default defineConfig((options) => ({
entry: ['src/index.ts'],
format: ['esm'],
minify: !options.watch, // Only minify in production
}))
minify: !options.watch, // Only minify in production
}));
```
### Browser Library
@@ -108,7 +112,7 @@ export default defineConfig({
platform: 'browser',
globalName: 'MyLib',
minify: true,
})
});
```
### Multiple Builds
@@ -129,7 +133,7 @@ export default defineConfig([
minify: true,
outDir: 'dist/prod',
},
])
]);
```
## CLI Examples
@@ -25,7 +25,7 @@ tsdown -d lib
export default defineConfig({
entry: ['src/index.ts'],
outDir: 'build',
})
});
```
## Common Patterns
@@ -36,12 +36,13 @@ export default defineConfig({
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
outDir: 'dist', // Default
outDir: 'dist', // Default
dts: true,
})
});
```
**Output:**
```
dist/
├── index.mjs
@@ -63,10 +64,11 @@ export default defineConfig([
format: ['cjs'],
outDir: 'dist/cjs',
},
])
]);
```
**Output:**
```
dist/
├── esm/
@@ -80,9 +82,9 @@ dist/
```ts
export default defineConfig({
entry: ['src/index.ts'],
outDir: 'lib', // Custom directory
outDir: 'lib', // Custom directory
clean: true,
})
});
```
### Build to Root
@@ -90,9 +92,9 @@ export default defineConfig({
```ts
export default defineConfig({
entry: ['src/index.ts'],
outDir: '.', // Output to project root (not recommended)
clean: false, // Don't clean root!
})
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.
@@ -111,19 +113,19 @@ export default defineConfig({
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` | `.mjs` | `.js` |
| `cjs` | `.cjs` | `.js` |
| `iife` | `.global.js` | `.global.js` |
| `umd` | `.umd.js` | `.umd.js` |
### ESM with .js Extension
@@ -132,7 +134,7 @@ export default defineConfig({
entry: ['src/index.ts'],
format: ['esm'],
outExtensions: () => ({ js: '.js' }),
})
});
```
Requires `"type": "module"` in package.json.
@@ -150,10 +152,11 @@ export default defineConfig({
utils: 'src/utils.ts',
},
outDir: 'dist',
})
});
```
**Output:**
```
dist/
├── index.mjs
@@ -166,11 +169,12 @@ dist/
export default defineConfig({
entry: ['src/**/*.ts', '!**/*.test.ts'],
outDir: 'dist',
unbundle: true, // Preserve structure
})
unbundle: true, // Preserve structure
});
```
**Output:**
```
dist/
├── index.mjs
@@ -189,14 +193,14 @@ export default defineConfig([
{
entry: ['src/index.ts'],
outDir: 'dist',
clean: true, // Clean first
clean: true, // Clean first
},
{
entry: ['src/cli.ts'],
outDir: 'dist',
clean: false, // Don't clean again
clean: false, // Don't clean again
},
])
]);
```
### Different Output Directories
@@ -213,7 +217,7 @@ export default defineConfig([
format: ['esm'],
outDir: 'dist/bin',
},
])
]);
```
## CLI Examples
@@ -8,12 +8,12 @@ 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 |
| 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
@@ -38,7 +38,7 @@ tsdown --format esm,cjs
export default defineConfig({
entry: ['src/index.ts'],
format: 'esm',
})
});
```
#### Multiple Formats
@@ -47,7 +47,7 @@ export default defineConfig({
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
})
});
```
## Per-Format Configuration
@@ -65,7 +65,7 @@ export default defineConfig({
target: ['node20'],
},
},
})
});
```
This allows different targets, platforms, or other settings per format.
@@ -79,10 +79,11 @@ 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)
@@ -96,7 +97,7 @@ export default defineConfig({
globalName: 'MyLib',
platform: 'browser',
minify: true,
})
});
```
Output: `dist/index.global.js` (IIFE with global `MyLib`)
@@ -109,7 +110,7 @@ export default defineConfig({
format: ['umd'],
globalName: 'MyLib',
platform: 'neutral',
})
});
```
Works with AMD, CommonJS, and browser globals.
@@ -123,7 +124,7 @@ export default defineConfig({
platform: 'node',
dts: true,
shims: true, // Add __dirname, __filename for CJS compat
})
});
```
### Framework Component Library
@@ -134,19 +135,19 @@ export default defineConfig({
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` |
| Format | Extension |
| ------ | -------------------------------------------- |
| ESM | `.mjs` or `.js` (with `"type": "module"`) |
| CJS | `.cjs` or `.js` (without `"type": "module"`) |
| IIFE | `.global.js` |
| UMD | `.umd.js` |
### Customize Extensions
@@ -159,7 +160,7 @@ export default defineConfig({
outExtensions: ({ format }) => ({
js: format === 'esm' ? '.js' : '.cjs',
}),
})
});
```
## Tips
@@ -24,7 +24,7 @@ export default defineConfig({
format: ['esm', 'cjs'],
dts: true,
exports: true,
})
});
```
## What Gets Generated
@@ -32,16 +32,18 @@ export default defineConfig({
### 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",
@@ -60,6 +62,7 @@ export default defineConfig({
### Multiple Entries
**Config:**
```ts
export default defineConfig({
entry: {
@@ -69,10 +72,11 @@ export default defineConfig({
format: ['esm', 'cjs'],
dts: true,
exports: true,
})
});
```
**Generated in package.json:**
```json
{
"main": "./dist/index.cjs",
@@ -104,7 +108,7 @@ export default defineConfig({
exports: {
all: true,
},
})
});
```
**Result:** All `.mjs`, `.cjs`, and `.d.ts` files will be added to exports.
@@ -122,14 +126,15 @@ export default defineConfig({
exports: {
devExports: true,
},
})
});
```
**Generated:**
```json
{
"exports": {
".": "./src/index.ts" // Points to source
".": "./src/index.ts" // Points to source
},
"publishConfig": {
"exports": {
@@ -153,10 +158,11 @@ export default defineConfig({
exports: {
devExports: 'development',
},
})
});
```
**Generated:**
```json
{
"exports": {
@@ -170,6 +176,7 @@ export default defineConfig({
```
**Use with TypeScript customConditions:**
```json
// tsconfig.json
{
@@ -189,15 +196,15 @@ export default defineConfig({
exports: {
customExports(pkg, context) {
// Add custom export
pkg['./foo'] = './dist/foo.js'
pkg['./foo'] = './dist/foo.js';
// Add package.json export
pkg['./package.json'] = './package.json'
pkg['./package.json'] = './package.json';
return pkg
return pkg;
},
},
})
});
```
## Common Patterns
@@ -211,7 +218,7 @@ export default defineConfig({
dts: true,
exports: true,
clean: true,
})
});
```
### Multiple Exports with Dev Mode
@@ -226,10 +233,10 @@ export default defineConfig({
format: ['esm', 'cjs'],
dts: true,
exports: {
all: false, // Only entries
all: false, // Only entries
devExports: 'development',
},
})
});
```
### Monorepo Package
@@ -240,8 +247,8 @@ export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
exports: true, // Generate for each package
})
exports: true, // Generate for each package
});
```
## Validation
@@ -259,8 +266,8 @@ Or in config:
```ts
export default defineConfig({
exports: true,
publint: true, // Validate exports
})
publint: true, // Validate exports
});
```
## Tips
@@ -8,11 +8,11 @@ Platform determines the runtime environment and affects module resolution, built
## 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 |
| 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
@@ -30,7 +30,7 @@ tsdown --platform neutral
export default defineConfig({
entry: ['src/index.ts'],
platform: 'browser',
})
});
```
## Platform Details
@@ -43,10 +43,11 @@ export default defineConfig({
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
@@ -61,10 +62,11 @@ 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
@@ -79,10 +81,11 @@ 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
@@ -97,8 +100,8 @@ export default defineConfig({
export default defineConfig({
entry: ['src/index.ts'],
format: ['cjs'],
platform: 'browser', // Ignored for CJS
})
platform: 'browser', // Ignored for CJS
});
```
See [rolldown PR #4693](https://github.com/rolldown/rolldown/pull/4693#issuecomment-2912229545) for details.
@@ -109,11 +112,11 @@ See [rolldown PR #4693](https://github.com/rolldown/rolldown/pull/4693#issuecomm
Different platforms check different `package.json` fields:
| Platform | mainFields | Priority |
|----------|------------|----------|
| `node` | `['main', 'module']` | main → module |
| Platform | mainFields | Priority |
| --------- | ------------------------------- | ----------------------- |
| `node` | `['main', 'module']` | main → module |
| `browser` | `['browser', 'module', 'main']` | browser → module → main |
| `neutral` | `[]` | Only `exports` field |
| `neutral` | `[]` | Only `exports` field |
### Neutral Platform Resolution
@@ -134,7 +137,7 @@ export default defineConfig({
mainFields: ['module', 'main'],
},
},
})
});
```
## Common Patterns
@@ -147,7 +150,7 @@ export default defineConfig({
format: ['esm'],
platform: 'node',
shims: true,
})
});
```
### Browser Library (IIFE)
@@ -159,7 +162,7 @@ export default defineConfig({
platform: 'browser',
globalName: 'MyLib',
minify: true,
})
});
```
### Universal Library
@@ -174,7 +177,7 @@ export default defineConfig({
mainFields: ['module', 'main'],
},
},
})
});
```
### React Component Library
@@ -185,7 +188,7 @@ export default defineConfig({
format: ['esm', 'cjs'],
platform: 'browser',
external: ['react', 'react-dom'],
})
});
```
### Node.js + Browser Builds
@@ -202,7 +205,7 @@ export default defineConfig([
format: ['esm'],
platform: 'browser',
},
])
]);
```
## Troubleshooting
@@ -216,6 +219,7 @@ 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
@@ -234,7 +238,7 @@ export default defineConfig({
conditions: ['import', 'require'],
},
},
})
});
```
## Tips
@@ -44,7 +44,7 @@ export default defineConfig({
entry: ['src/index.ts'],
format: ['esm'],
shims: true,
})
});
```
## Generated Code
@@ -52,56 +52,62 @@ export default defineConfig({
### ESM with Shims
**Source:**
```ts
console.log(__dirname)
console.log(__filename)
console.log(__dirname);
console.log(__filename);
```
**Output (shims: true):**
```js
import { fileURLToPath } from 'node:url'
import { dirname } from 'node:path'
import { fileURLToPath } from 'node:url';
import { dirname } from 'node:path';
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
console.log(__dirname)
console.log(__filename)
console.log(__dirname);
console.log(__filename);
```
### ESM with require
**Source:**
```ts
const mod = require('some-module')
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')
```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)
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
}
filename: __filename,
};
console.log(import_meta.url)
console.log(import_meta.dirname)
console.log(import_meta.url);
console.log(import_meta.dirname);
```
## Common Patterns
@@ -113,8 +119,8 @@ export default defineConfig({
entry: ['src/cli.ts'],
format: ['esm'],
platform: 'node',
shims: true, // Add __dirname, __filename
})
shims: true, // Add __dirname, __filename
});
```
### Dual Format Library
@@ -124,9 +130,9 @@ export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
platform: 'node',
shims: true, // ESM gets __dirname/__filename
// CJS gets import.meta.* (automatic)
})
shims: true, // ESM gets __dirname/__filename
// CJS gets import.meta.* (automatic)
});
```
### Server-Side Code
@@ -137,19 +143,19 @@ export default defineConfig({
format: ['esm'],
platform: 'node',
shims: true,
external: [/.*/], // External all deps
})
external: [/.*/], // External all deps
});
```
### File System Operations
```ts
// Source code
import { readFileSync } from 'fs'
import { join } from 'path'
import { readFileSync } from 'fs';
import { join } from 'path';
// Read file relative to current module
const content = readFileSync(join(__dirname, 'data.json'), 'utf-8')
const content = readFileSync(join(__dirname, 'data.json'), 'utf-8');
```
```ts
@@ -157,8 +163,8 @@ const content = readFileSync(join(__dirname, 'data.json'), 'utf-8')
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm'],
shims: true, // Enables __dirname
})
shims: true, // Enables __dirname
});
```
## When to Use Shims
@@ -186,11 +192,11 @@ Shims add minimal runtime overhead:
```js
// Added to output when shims enabled
import { fileURLToPath } from 'node:url'
import { dirname } from 'node:path'
import { fileURLToPath } from 'node:url';
import { dirname } from 'node:path';
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
```
### Tree Shaking
@@ -205,8 +211,8 @@ If `__dirname` or `__filename` are not used, they're automatically removed durin
export default defineConfig({
platform: 'node',
format: ['esm'],
shims: true, // Recommended for Node.js
})
shims: true, // Recommended for Node.js
});
```
- `require` shim added automatically
@@ -218,8 +224,8 @@ export default defineConfig({
export default defineConfig({
platform: 'browser',
format: ['esm'],
shims: false, // Not needed for browser
})
shims: false, // Not needed for browser
});
```
- Shims not needed (no Node.js variables)
@@ -231,8 +237,8 @@ export default defineConfig({
export default defineConfig({
platform: 'neutral',
format: ['esm'],
shims: false, // Avoid platform-specific code
})
shims: false, // Avoid platform-specific code
});
```
- Avoid shims for maximum portability
@@ -259,7 +265,7 @@ Enable shims:
```ts
export default defineConfig({
shims: true,
})
});
```
### `require is not defined` in ESM
@@ -268,8 +274,8 @@ Automatic on Node.js platform. If not working:
```ts
export default defineConfig({
platform: 'node', // Ensure Node.js platform
})
platform: 'node', // Ensure Node.js platform
});
```
### Import.meta not working in CJS
@@ -278,8 +284,8 @@ Automatic - no configuration needed. If still failing, check output format:
```ts
export default defineConfig({
format: ['cjs'], // Shims added automatically
})
format: ['cjs'], // Shims added automatically
});
```
## Tips
@@ -23,7 +23,7 @@ tsdown --sourcemap inline
export default defineConfig({
entry: ['src/index.ts'],
sourcemap: true,
})
});
```
## Source Map Types
@@ -34,15 +34,17 @@ Generates separate `.map` files:
```ts
export default defineConfig({
sourcemap: true, // or 'external'
})
sourcemap: true, // or 'external'
});
```
**Output:**
- `dist/index.mjs`
- `dist/index.mjs.map`
**Pros:**
- Smaller bundle size
- Can be excluded from production
- Faster parsing
@@ -54,17 +56,20 @@ 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
@@ -75,14 +80,16 @@ 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
@@ -110,9 +117,9 @@ This also generates `.d.ts.map` files for TypeScript declarations.
```ts
export default defineConfig((options) => ({
entry: ['src/index.ts'],
sourcemap: options.watch, // Only in dev
sourcemap: options.watch, // Only in dev
minify: !options.watch,
}))
}));
```
### Production with External Maps
@@ -121,9 +128,9 @@ export default defineConfig((options) => ({
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
sourcemap: true, // External maps
sourcemap: true, // External maps
minify: true,
})
});
```
Deploy maps to separate error reporting service.
@@ -135,7 +142,7 @@ export default defineConfig({
entry: ['src/index.ts'],
format: ['esm'],
sourcemap: 'inline',
})
});
```
### Per-Format Source Maps
@@ -148,10 +155,10 @@ export default defineConfig({
sourcemap: true,
},
iife: {
sourcemap: 'inline', // Inline for browser
sourcemap: 'inline', // Inline for browser
},
},
})
});
```
### TypeScript Library with Declaration Maps
@@ -162,12 +169,13 @@ export default defineConfig({
format: ['esm', 'cjs'],
sourcemap: true,
dts: {
sourcemap: true, // Enable declaration maps
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`
@@ -188,12 +196,12 @@ export default defineConfig({
## 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 |
| 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
@@ -225,16 +233,16 @@ tsdown --no-sourcemap
export default defineConfig({
sourcemap: true,
minify: false,
})
});
```
### Production Build
```ts
export default defineConfig({
sourcemap: 'external', // Upload to error service
sourcemap: 'external', // Upload to error service
minify: true,
})
});
```
### Browser Library
@@ -243,9 +251,9 @@ export default defineConfig({
export default defineConfig({
format: ['iife'],
platform: 'browser',
sourcemap: 'inline', // Self-contained
sourcemap: 'inline', // Self-contained
globalName: 'MyLib',
})
});
```
### Node.js CLI Tool
@@ -256,7 +264,7 @@ export default defineConfig({
platform: 'node',
sourcemap: true,
shims: true,
})
});
```
## Troubleshooting
@@ -274,8 +282,8 @@ Use external source maps instead of inline:
```ts
export default defineConfig({
sourcemap: true, // Not 'inline'
})
sourcemap: true, // Not 'inline'
});
```
### Source Not Found
@@ -32,14 +32,16 @@ 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
@@ -66,7 +68,7 @@ tsdown --no-target
export default defineConfig({
entry: ['src/index.ts'],
target: 'es2020',
})
});
```
### Multiple Targets
@@ -75,7 +77,7 @@ export default defineConfig({
export default defineConfig({
entry: ['src/index.ts'],
target: ['chrome100', 'safari15', 'node18'],
})
});
```
## Supported Targets
@@ -101,7 +103,7 @@ export default defineConfig({
entry: ['src/index.ts'],
format: ['esm'],
target: ['chrome100', 'safari15', 'firefox100'],
})
});
```
### Node.js Library
@@ -111,7 +113,7 @@ export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
target: 'node18',
})
});
```
### Legacy Support
@@ -120,8 +122,8 @@ export default defineConfig({
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm'],
target: 'es2015', // Maximum compatibility
})
target: 'es2015', // Maximum compatibility
});
```
### Per-Format Targets
@@ -137,7 +139,7 @@ export default defineConfig({
target: 'node16',
},
},
})
});
```
## Decorators
@@ -168,8 +170,8 @@ See [oxc issue #9170](https://github.com/oxc-project/oxc/issues/9170).
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
target: 'es2020', // Wide compatibility
})
target: 'es2020', // Wide compatibility
});
```
### Modern-Only Library
@@ -178,8 +180,8 @@ export default defineConfig({
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm'],
target: false, // No transformations
})
target: false, // No transformations
});
```
### Browser Component
@@ -190,7 +192,7 @@ export default defineConfig({
format: ['esm'],
target: ['chrome100', 'safari15', 'firefox100'],
platform: 'browser',
})
});
```
## Tips
@@ -199,7 +201,7 @@ export default defineConfig({
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
5. **Test output** in target environments
## Related Options
@@ -25,8 +25,8 @@ tsdown --no-treeshake
```ts
export default defineConfig({
entry: ['src/index.ts'],
treeshake: true, // Default
})
treeshake: true, // Default
});
```
## How It Works
@@ -34,28 +34,30 @@ export default defineConfig({
### With Tree Shaking
**Source:**
```ts
// src/util.ts
export function unused() {
console.log("I'm unused")
console.log("I'm unused");
}
export function hello(x: number) {
console.log('Hello World', x)
console.log('Hello World', x);
}
// src/index.ts
import { hello } from './util'
hello(1)
import { hello } from './util';
hello(1);
```
**Output:**
```js
// dist/index.mjs
function hello(x) {
console.log('Hello World', x)
console.log('Hello World', x);
}
hello(1)
hello(1);
```
`unused()` function is removed because it's never imported.
@@ -63,16 +65,17 @@ hello(1)
### Without Tree Shaking
**Output:**
```js
// dist/index.mjs
function unused() {
console.log("I'm unused")
console.log("I'm unused");
}
function hello(x) {
console.log('Hello World', x)
console.log('Hello World', x);
}
hello(1)
hello(1);
```
All code is included, even if unused.
@@ -84,7 +87,7 @@ All code is included, even if unused.
```ts
export default defineConfig({
treeshake: true,
})
});
```
Uses Rolldown's default tree shaking.
@@ -98,7 +101,7 @@ export default defineConfig({
propertyReadSideEffects: false,
unknownGlobalSideEffects: false,
},
})
});
```
See [Rolldown docs](https://rolldown.rs/reference/config-options#treeshake) for all options.
@@ -108,7 +111,7 @@ See [Rolldown docs](https://rolldown.rs/reference/config-options#treeshake) for
```ts
export default defineConfig({
treeshake: false,
})
});
```
## Side Effects
@@ -138,10 +141,10 @@ export default defineConfig({
treeshake: {
moduleSideEffects: (id) => {
// Preserve side effects for polyfills
return id.includes('polyfill')
return id.includes('polyfill');
},
},
})
});
```
## Common Patterns
@@ -154,7 +157,7 @@ export default defineConfig({
format: ['esm', 'cjs'],
treeshake: true,
minify: true,
})
});
```
### Development Build
@@ -162,8 +165,8 @@ export default defineConfig({
```ts
export default defineConfig((options) => ({
entry: ['src/index.ts'],
treeshake: !options.watch, // Disable in dev
}))
treeshake: !options.watch, // Disable in dev
}));
```
### Library with Side Effects
@@ -173,14 +176,10 @@ export default defineConfig({
entry: ['src/index.ts'],
treeshake: {
moduleSideEffects: (id) => {
return (
id.includes('.css') ||
id.includes('polyfill') ||
id.includes('side-effect')
)
return id.includes('.css') || id.includes('polyfill') || id.includes('side-effect');
},
},
})
});
```
### Utilities Library
@@ -191,12 +190,13 @@ export default defineConfig({
format: ['esm'],
treeshake: true,
dts: true,
})
});
```
Users can import only what they need:
```ts
import { onlyWhatINeed } from 'my-utils'
import { onlyWhatINeed } from 'my-utils';
```
## Benefits
@@ -228,7 +228,7 @@ During development to see all code:
```ts
export default defineConfig((options) => ({
treeshake: !options.watch,
}))
}));
```
### Side Effect Code
@@ -237,7 +237,7 @@ Code with global side effects:
```ts
// This has side effects
window.myGlobal = {}
window.myGlobal = {};
export function setup() {
// ...
@@ -259,7 +259,7 @@ Include all code for coverage:
```ts
export default defineConfig({
treeshake: false,
})
});
```
## Tips
@@ -297,15 +297,15 @@ export default defineConfig({
```ts
// utils.ts - perfect for tree shaking
export function add(a, b) {
return a + b
return a + b;
}
export function multiply(a, b) {
return a * b
return a * b;
}
// Only 'add' imported = only 'add' bundled
import { add } from './utils'
import { add } from './utils';
```
### With Side Effects
@@ -313,12 +313,12 @@ import { add } from './utils'
```ts
// polyfill.ts - has side effects
if (!Array.prototype.at) {
Array.prototype.at = function(index) {
Array.prototype.at = function (index) {
// polyfill implementation
}
};
}
export {} // Need to export something
export {}; // Need to export something
```
```json
@@ -20,7 +20,7 @@ tsdown --unbundle
export default defineConfig({
entry: ['src/**/*.ts', '!**/*.test.ts'],
unbundle: true,
})
});
```
## How It Works
@@ -40,14 +40,16 @@ src/
### With Unbundle
**Config:**
```ts
export default defineConfig({
entry: ['src/index.ts'],
unbundle: true,
})
});
```
**Output:**
```
dist/
├── index.mjs
@@ -63,6 +65,7 @@ All imported files are output individually, preserving structure.
### Without Unbundle (Default)
**Output:**
```
dist/
└── index.mjs (all code bundled together)
@@ -97,19 +100,21 @@ export default defineConfig({
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'
import { helper } from 'my-lib/utils/helper';
import { Button } from 'my-lib/components/button';
```
### Monorepo Shared Package
@@ -120,7 +125,7 @@ export default defineConfig({
format: ['esm'],
unbundle: true,
outDir: 'dist',
})
});
```
### TypeScript Compilation Only
@@ -133,7 +138,7 @@ export default defineConfig({
minify: false,
treeshake: false,
dts: true,
})
});
```
Pure TypeScript to JavaScript transformation.
@@ -143,9 +148,9 @@ Pure TypeScript to JavaScript transformation.
```ts
export default defineConfig((options) => ({
entry: ['src/**/*.ts'],
unbundle: options.watch, // Unbundle in dev only
unbundle: options.watch, // Unbundle in dev only
minify: !options.watch,
}))
}));
```
Fast rebuilds during development, optimized for production.
@@ -156,14 +161,9 @@ Fast rebuilds during development, optimized for production.
```ts
export default defineConfig({
entry: [
'src/**/*.ts',
'!**/*.test.ts',
'!**/*.spec.ts',
'!**/fixtures/**',
],
entry: ['src/**/*.ts', '!**/*.test.ts', '!**/*.spec.ts', '!**/fixtures/**'],
unbundle: true,
})
});
```
### Multiple Entry Points
@@ -175,7 +175,7 @@ export default defineConfig({
cli: 'src/cli.ts',
},
unbundle: true,
})
});
```
Both entry files and all imports preserved.
@@ -189,7 +189,7 @@ export default defineConfig({
entry: ['src/**/*.ts'],
unbundle: true,
outExtensions: () => ({ js: '.js' }),
})
});
```
### Preserve Directory
@@ -199,10 +199,11 @@ export default defineConfig({
entry: ['src/**/*.ts'],
unbundle: true,
outDir: 'lib',
})
});
```
**Output:**
```
lib/
├── index.js
@@ -233,21 +234,22 @@ 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 |
| 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
@@ -255,6 +257,7 @@ Unbundle is typically faster:
### Bundle Size
Unbundle produces larger output:
- Each file has its own overhead
- No cross-module optimizations
- User's bundler handles final optimization
@@ -30,7 +30,7 @@ tsdown --watch ./src/index.ts
export default defineConfig({
entry: ['src/index.ts'],
watch: true,
})
});
```
## Watch Options
@@ -49,7 +49,7 @@ export default defineConfig({
watch: {
exclude: ['test/**', '**/*.test.ts'],
},
})
});
```
### On Success Command
@@ -66,7 +66,7 @@ export default defineConfig({
entry: ['src/index.ts'],
watch: true,
onSuccess: 'node dist/index.mjs',
})
});
```
## Watch Behavior
@@ -74,6 +74,7 @@ export default defineConfig({
### Default Watch Targets
By default, tsdown watches:
- All entry files
- All imported files
- Config file (triggers restart)
@@ -87,6 +88,7 @@ By default, tsdown watches:
### Keyboard Shortcuts
During watch mode:
- `r` - Manual rebuild
- `q` - Quit watch mode
@@ -101,7 +103,7 @@ export default defineConfig((options) => ({
watch: options.watch,
sourcemap: options.watch,
minify: !options.watch,
}))
}));
```
### With Post-Build Script
@@ -111,7 +113,7 @@ export default defineConfig({
entry: ['src/index.ts'],
watch: true,
onSuccess: 'npm run test',
})
});
```
### Multiple Entry Points
@@ -123,8 +125,8 @@ export default defineConfig({
cli: 'src/cli.ts',
},
watch: true,
clean: false, // Don't clean on each rebuild
})
clean: false, // Don't clean on each rebuild
});
```
### Test Runner Integration
@@ -147,7 +149,7 @@ export default defineConfig({
watch: {
exclude: ['**/test/**', '**/*.spec.ts'],
},
})
});
```
## Advanced Configuration
@@ -162,23 +164,23 @@ export default defineConfig({
exclude: ['**/*.test.ts', '**/fixtures/**'],
skipWrite: false,
},
})
});
```
### Conditional Watch
```ts
export default defineConfig((options) => {
const isDev = options.watch
const isDev = options.watch;
return {
entry: ['src/index.ts'],
format: ['esm'],
dts: !isDev, // Skip DTS in watch mode
dts: !isDev, // Skip DTS in watch mode
sourcemap: isDev,
clean: !isDev,
}
})
};
});
```
## CLI Examples
@@ -230,14 +232,9 @@ Add ignore patterns:
```ts
export default defineConfig({
watch: {
exclude: [
'**/node_modules/**',
'**/.git/**',
'**/dist/**',
'**/*.test.ts',
],
exclude: ['**/node_modules/**', '**/.git/**', '**/dist/**', '**/*.test.ts'],
},
})
});
```
### Slow Rebuilds
@@ -30,18 +30,18 @@ export default defineConfig({
platform: 'neutral',
external: ['react', 'react-dom'],
dts: true,
})
});
```
### Component Example
```tsx
// src/MyButton.tsx
import React from 'react'
import React from 'react';
interface MyButtonProps {
type?: 'primary' | 'secondary'
onClick?: () => void
type?: 'primary' | 'secondary';
onClick?: () => void;
}
export const MyButton: React.FC<MyButtonProps> = ({ type = 'primary', onClick }) => {
@@ -49,13 +49,13 @@ export const MyButton: React.FC<MyButtonProps> = ({ type = 'primary', onClick })
<button className={`btn btn-${type}`} onClick={onClick}>
Click me
</button>
)
}
);
};
```
```ts
// src/index.ts
export { MyButton } from './MyButton'
export { MyButton } from './MyButton';
```
## JSX Transform
@@ -68,10 +68,11 @@ Modern JSX transform (React 17+):
export default defineConfig({
entry: ['src/index.tsx'],
// Automatic JSX is default
})
});
```
**Characteristics:**
- No `import React` needed
- Smaller bundle size
- React 17+ required
@@ -85,13 +86,14 @@ export default defineConfig({
entry: ['src/index.tsx'],
inputOptions: {
transform: {
jsx: 'react', // Classic transform
jsx: 'react', // Classic transform
},
},
})
});
```
**Characteristics:**
- Requires `import React from 'react'`
- Compatible with older React versions
@@ -108,7 +110,7 @@ pnpm add -D @rollup/plugin-babel babel-plugin-react-compiler
### Configure
```ts
import pluginBabel from '@rollup/plugin-babel'
import pluginBabel from '@rollup/plugin-babel';
export default defineConfig({
entry: ['src/index.tsx'],
@@ -126,7 +128,7 @@ export default defineConfig({
}),
],
dts: true,
})
});
```
## Common Patterns
@@ -141,11 +143,11 @@ export default defineConfig({
external: [
'react',
'react-dom',
/^react\//, // react/jsx-runtime, etc.
/^react\//, // react/jsx-runtime, etc.
],
dts: true,
clean: true,
})
});
```
### Multiple Components
@@ -161,7 +163,7 @@ export default defineConfig({
format: ['esm', 'cjs'],
external: ['react', 'react-dom'],
dts: true,
})
});
```
### Hooks Library
@@ -171,10 +173,10 @@ export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
platform: 'neutral',
external: ['react'], // Only React needed
external: ['react'], // Only React needed
dts: true,
treeshake: true,
})
});
```
### Monorepo React Packages
@@ -187,10 +189,10 @@ export default defineConfig({
external: [
'react',
'react-dom',
/^@mycompany\//, // Other workspace packages
/^@mycompany\//, // Other workspace packages
],
dts: true,
})
});
```
## TypeScript Configuration
@@ -203,11 +205,11 @@ export default defineConfig({
"target": "ES2020",
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"jsx": "react-jsx", // or "react" for classic
"jsx": "react-jsx", // or "react" for classic
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"strict": true,
"isolatedDeclarations": true, // Fast DTS generation
"isolatedDeclarations": true, // Fast DTS generation
"skipLibCheck": true
},
"include": ["src"]
@@ -252,7 +254,7 @@ export default defineConfig({
### With Fast Refresh (Development)
```ts
import react from '@vitejs/plugin-react'
import react from '@vitejs/plugin-react';
export default defineConfig((options) => ({
entry: ['src/index.ts'],
@@ -264,7 +266,7 @@ export default defineConfig((options) => ({
react({ fastRefresh: true }),
]
: [],
}))
}));
```
## Tips
@@ -284,7 +286,7 @@ export default defineConfig((options) => ({
Ensure React is externalized:
```ts
external: ['react', 'react-dom', /^react\//]
external: ['react', 'react-dom', /^react\//];
```
### Type Errors with JSX
@@ -294,7 +296,7 @@ Check `tsconfig.json`:
```json
{
"compilerOptions": {
"jsx": "react-jsx" // or "react"
"jsx": "react-jsx" // or "react"
}
}
```
@@ -304,12 +306,7 @@ Check `tsconfig.json`:
Add to external patterns:
```ts
external: [
'react',
'react-dom',
'react/jsx-runtime',
'react/jsx-dev-runtime',
]
external: ['react', 'react-dom', 'react/jsx-runtime', 'react/jsx-dev-runtime'];
```
## Related
@@ -26,21 +26,19 @@ pnpm add -D unplugin-vue vue-tsc
```ts
// tsdown.config.ts
import { defineConfig } from 'tsdown'
import Vue from 'unplugin-vue/rolldown'
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 }),
],
plugins: [Vue({ isProduction: true })],
dts: {
vue: true, // Enable Vue type generation
vue: true, // Enable Vue type generation
},
})
});
```
## How It Works
@@ -48,6 +46,7 @@ export default defineConfig({
### unplugin-vue
Compiles `.vue` single-file components:
- Transforms template to render functions
- Handles scoped styles
- Processes script setup
@@ -55,6 +54,7 @@ Compiles `.vue` single-file components:
### vue-tsc
Generates TypeScript declarations:
- Type-checks Vue components
- Creates `.d.ts` files
- Preserves component props types
@@ -68,22 +68,18 @@ Generates TypeScript declarations:
<!-- src/Button.vue -->
<script setup lang="ts">
interface Props {
type?: 'primary' | 'secondary'
disabled?: boolean
type?: 'primary' | 'secondary';
disabled?: boolean;
}
defineProps<Props>()
defineProps<Props>();
defineEmits<{
click: []
}>()
click: [];
}>();
</script>
<template>
<button
:class="['btn', `btn-${type}`]"
:disabled="disabled"
@click="$emit('click')"
>
<button :class="['btn', `btn-${type}`]" :disabled="disabled" @click="$emit('click')">
<slot />
</button>
</template>
@@ -105,12 +101,12 @@ defineEmits<{
```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'
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'
export type { ButtonProps } from './Button.vue';
```
## Common Patterns
@@ -135,7 +131,7 @@ export default defineConfig({
vue: true,
},
clean: true,
})
});
```
### Multiple Components
@@ -152,20 +148,20 @@ export default defineConfig({
external: ['vue'],
plugins: [Vue({ isProduction: true })],
dts: { vue: true },
})
});
```
### With Composition Utilities
```ts
// src/composables/useCounter.ts
import { ref } from 'vue'
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 }
const count = ref(initial);
const increment = () => count.value++;
const decrement = () => count.value--;
return { count, increment, decrement };
}
```
@@ -176,7 +172,7 @@ export default defineConfig({
external: ['vue'],
plugins: [Vue({ isProduction: true })],
dts: { vue: true },
})
});
```
### TypeScript Configuration
@@ -215,7 +211,7 @@ export default defineConfig({
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
},
}
},
"files": ["dist"],
"peerDependencies": {
@@ -238,8 +234,8 @@ export default defineConfig({
Some Vite Vue plugins may work:
```ts
import Vue from 'unplugin-vue/rolldown'
import Components from 'unplugin-vue-components/rolldown'
import Vue from 'unplugin-vue/rolldown';
import Components from 'unplugin-vue-components/rolldown';
export default defineConfig({
entry: ['src/index.ts'],
@@ -251,7 +247,7 @@ export default defineConfig({
}),
],
dts: { vue: true },
})
});
```
### JSX Support
@@ -276,7 +272,7 @@ export default defineConfig({
},
},
dts: { vue: true },
})
});
```
### Monorepo Vue Packages
@@ -289,7 +285,7 @@ export default defineConfig({
external: ['vue', /^@mycompany\//],
plugins: [Vue({ isProduction: true })],
dts: { vue: true },
})
});
```
## Plugin Options
@@ -311,7 +307,7 @@ Vue({
isCustomElement: (tag) => tag.startsWith('custom-'),
},
},
})
});
```
## Tips
@@ -328,18 +324,23 @@ Vue({
### Type Generation Fails
Ensure vue-tsc is installed:
```bash
pnpm add -D vue-tsc
```
Enable in config:
```ts
dts: { vue: true }
dts: {
vue: true;
}
```
### Component Types Missing
Check TypeScript config:
```json
{
"compilerOptions": {
@@ -352,13 +353,15 @@ Check TypeScript config:
### Vue Not Externalized
Add to external:
```ts
external: ['vue']
external: ['vue'];
```
### SFC Compilation Errors
Check unplugin-vue version:
```bash
pnpm add -D unplugin-vue@latest
```
@@ -17,13 +17,13 @@ pnpm add -D rolldown-plugin-wasm
### Configure
```ts
import { wasm } from 'rolldown-plugin-wasm'
import { defineConfig } from 'tsdown'
import { wasm } from 'rolldown-plugin-wasm';
import { defineConfig } from 'tsdown';
export default defineConfig({
entry: ['./src/index.ts'],
plugins: [wasm()],
})
});
```
### TypeScript Support
@@ -33,8 +33,8 @@ Add type declarations to `tsconfig.json`:
```jsonc
{
"compilerOptions": {
"types": ["rolldown-plugin-wasm/types"]
}
"types": ["rolldown-plugin-wasm/types"],
},
}
```
@@ -43,8 +43,8 @@ Add type declarations to `tsconfig.json`:
### Direct Import
```ts
import { add } from './add.wasm'
add(1, 2)
import { add } from './add.wasm';
add(1, 2);
```
### Async Init
@@ -52,9 +52,9 @@ add(1, 2)
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)
import init from './add.wasm?init';
const instance = await init(imports); // imports optional
instance.exports.add(1, 2);
```
### Sync Init
@@ -62,9 +62,9 @@ instance.exports.add(1, 2)
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)
import initSync from './add.wasm?init&sync';
const instance = initSync(imports); // imports optional
instance.exports.add(1, 2);
```
## wasm-bindgen Support
@@ -72,31 +72,31 @@ instance.exports.add(1, 2)
### Target `bundler` (Recommended)
```ts
import { add } from 'some-pkg'
add(1, 2)
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'
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)
});
add(1, 2);
```
### Target `web` (Browser)
```ts
import init, { add } from 'some-pkg/add.js'
import wasmUrl from 'some-pkg/add_bg.wasm?url'
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)
await init({ module_or_path: wasmUrl });
add(1, 2);
```
`nodejs` and `no-modules` wasm-bindgen targets are not supported.
@@ -107,17 +107,17 @@ add(1, 2)
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'
})
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 |
| 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
@@ -9,6 +9,7 @@ All CLI flags can also be set in the config file. CLI flags override config file
## Flag Patterns
CLI flag mapping rules:
- `--foo` sets `foo: true`
- `--no-foo` sets `foo: false`
- `--foo.bar` sets `foo: { bar: true }`