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