base
> Base tsup configuration for jmlweb projects. Provides sensible defaults and a clean API for creating consistent build configurations.
✨ Features
Section titled “✨ Features”- 🎯 Sensible Defaults: Pre-configured with common settings for TypeScript libraries
- 📦 Dual Format: Generates both CommonJS and ESM outputs by default
- 📝 TypeScript Declarations: Automatic
.d.tsgeneration enabled - 🔧 Clean API: Simple function to create configurations with external dependencies
- ⚡ Zero Config: Works out of the box with minimal setup
- 🛠️ Fully Typed: Complete TypeScript support with exported types
- 🖥️ CLI Preset: Specialized configuration for CLI packages with shebang support
📦 Installation
Section titled “📦 Installation”pnpm add -D @jmlweb/tsup-config-base tsup> 💡 Upgrading from a previous version? See the Migration Guide for breaking changes and upgrade instructions.
🚀 Quick Start
Section titled “🚀 Quick Start”Create a tsup.config.ts file in your project root:
import { createTsupConfig } from '@jmlweb/tsup-config-base';
export default createTsupConfig();💡 Examples
Section titled “💡 Examples”Basic Setup (No Externals)
Section titled “Basic Setup (No Externals)”import { createTsupConfig } from '@jmlweb/tsup-config-base';
export default createTsupConfig();With External Dependencies
Section titled “With External Dependencies”import { createTsupConfig } from '@jmlweb/tsup-config-base';
export default createTsupConfig({ external: ['eslint', 'typescript-eslint', '@eslint/js'],});With Internal Workspace Dependencies
Section titled “With Internal Workspace Dependencies”import { createTsupConfig } from '@jmlweb/tsup-config-base';
export default createTsupConfig({ external: [ // Internal packages '@jmlweb/eslint-config-base-js', // External peer dependencies '@eslint/js', 'eslint', 'eslint-config-prettier', 'typescript-eslint', ],});Custom Entry Point
Section titled “Custom Entry Point”import { createTsupConfig } from '@jmlweb/tsup-config-base';
export default createTsupConfig({ entry: ['src/main.ts'], external: ['some-dependency'],});With Additional Options
Section titled “With Additional Options”import { createTsupConfig } from '@jmlweb/tsup-config-base';
export default createTsupConfig({ external: ['vitest'], options: { minify: true, sourcemap: true, splitting: true, },});Multiple Entry Points
Section titled “Multiple Entry Points”import { createTsupConfig } from '@jmlweb/tsup-config-base';
export default createTsupConfig({ entry: ['src/index.ts', 'src/cli.ts'], external: ['commander'],});Object-Style Entry Points
Section titled “Object-Style Entry Points”import { createTsupConfig } from '@jmlweb/tsup-config-base';
export default createTsupConfig({ entry: { index: 'src/index.ts', utils: 'src/utils/index.ts', },});CLI Package Configuration
Section titled “CLI Package Configuration”For CLI packages that need shebang injection, use createTsupCliConfig:
import { createTsupCliConfig } from '@jmlweb/tsup-config-base';
export default createTsupCliConfig();// Output: dist/cli.js with #!/usr/bin/env node shebangCLI with Custom Entry
Section titled “CLI with Custom Entry”import { createTsupCliConfig } from '@jmlweb/tsup-config-base';
export default createTsupCliConfig({ entry: { bin: 'src/bin.ts' }, external: ['commander'],});CLI with Library API
Section titled “CLI with Library API”import { createTsupCliConfig } from '@jmlweb/tsup-config-base';
export default createTsupCliConfig({ entry: { cli: 'src/cli.ts', index: 'src/index.ts', }, shebang: 'cli', // Only add shebang to cli entry external: ['commander'],});🤔 Why Use This?
Section titled “🤔 Why Use This?”> Philosophy: TypeScript libraries should publish both CommonJS and ESM formats with type declarations for maximum compatibility across all consuming projects.
This package provides a tsup configuration optimized for building TypeScript libraries with dual-format output. It handles the complexity of generating both CommonJS and ESM builds while maintaining proper type definitions and ensuring external dependencies aren’t bundled.
Design Decisions
Section titled “Design Decisions”Dual Format Output (format: ['cjs', 'esm']): Support both module systems
- Why: The JavaScript ecosystem is in transition from CommonJS to ESM. Publishing both formats ensures your library works in all environments - legacy Node.js projects using require(), modern ESM projects using import, and bundlers that optimize based on format. This maximizes compatibility
- Trade-off: Slightly larger published package size (two builds). But consumers only use one format, and the compatibility benefit is essential
- When to override: For internal packages consumed only by ESM projects, you can use
['esm']only. But dual publishing is safer for public libraries
Type Declaration Generation (dts: true): Automatic .d.ts files
- Why: TypeScript consumers need type definitions for intellisense, type checking, and developer experience. Generating declarations automatically ensures your library provides first-class TypeScript support without manual maintenance
- Trade-off: Slightly slower builds due to declaration generation. But type safety for consumers is non-negotiable
- When to override: Never for libraries meant to be consumed - types are essential for modern JavaScript development
External Dependencies (external array): Control bundling
- Why: Libraries shouldn’t bundle their dependencies - this leads to duplicate code, version conflicts, and bloated packages. The
externalparameter lets you specify which dependencies should remain as imports, letting consumers manage versions - Trade-off: Must carefully specify which dependencies are external (typically all dependencies and peerDependencies)
- When to override: For standalone CLI tools, you might bundle all dependencies. But for libraries, externals are crucial
Clean Builds (clean: true): Fresh output on every build
- Why: Cleaning the output directory prevents stale files from previous builds causing issues. Ensures deterministic builds and prevents shipping renamed or deleted files
- Trade-off: Very slightly slower builds (must delete files first). But the reliability is worth it
- When to override: Rarely - clean builds prevent an entire class of mysterious bugs
📋 Configuration Details
Section titled “📋 Configuration Details”Default Settings
Section titled “Default Settings”| Setting | Default Value | Description |
|---|---|---|
entry | ['src/index.ts'] | Entry point(s) for the build |
format | ['cjs', 'esm'] | Output formats (dual publishing) |
dts | true | Generate TypeScript declarations |
clean | true | Clean output directory before build |
outDir | 'dist' | Output directory |
external | [] | External packages to exclude |
API Reference
Section titled “API Reference”createTsupConfig(options?: TsupConfigOptions): Options
Section titled “createTsupConfig(options?: TsupConfigOptions): Options”Creates a tsup configuration with sensible defaults for library packages.
Parameters:
| Option | Type | Default | Description |
|---|---|---|---|
entry | string[] | Record<string, string> | ['src/index.ts'] | Entry point files |
format | ('cjs' | 'esm' | 'iife')[] | ['cjs', 'esm'] | Output formats |
dts | boolean | true | Generate declaration files |
clean | boolean | true | Clean output before build |
outDir | string | 'dist' | Output directory |
external | (string | RegExp)[] | [] | Packages to exclude from bundle |
options | Partial<Options> | {} | Additional tsup options to merge |
Returns: A complete tsup Options object.
createTsupCliConfig(options?: TsupCliConfigOptions): Options | Options[]
Section titled “createTsupCliConfig(options?: TsupCliConfigOptions): Options | Options[]”Creates a CLI-specific tsup configuration with shebang support.
Parameters:
| Option | Type | Default | Description |
|---|---|---|---|
entry | string[] | Record<string, string> | { cli: 'src/cli.ts' } | Entry point files |
format | ('cjs' | 'esm' | 'iife')[] | ['esm'] | Output formats (ESM only by default) |
dts | boolean | true | Generate declaration files |
clean | boolean | true | Clean output before build |
outDir | string | 'dist' | Output directory |
external | (string | RegExp)[] | [] | Packages to exclude from bundle |
target | NodeTarget | 'node18' | Node.js target version |
shebang | boolean | string | string[] | true | Add shebang to entries (true = all entries) |
options | Partial<Options> | {} | Additional tsup options to merge |
Returns: A tsup Options object, or an array of Options when selective shebang is used.
Exported Constants
Section titled “Exported Constants”BASE_DEFAULTS- Default library configuration valuesCLI_DEFAULTS- Default CLI configuration valuesOptions- Re-exported from tsup
Type Exports
Section titled “Type Exports”EntryConfig- Entry point configuration type (string[] | Record<string, string>)NodeTarget- Node.js target version type ('node16' | 'node18' | 'node20' | 'node22' | ...)TsupConfigOptions- Options forcreateTsupConfigTsupCliConfigOptions- Options forcreateTsupCliConfig
🎯 When to Use
Section titled “🎯 When to Use”Use this configuration when you want:
- ✅ Consistent build configuration across multiple packages
- ✅ Dual-format output (CommonJS + ESM) for maximum compatibility
- ✅ Automatic TypeScript declaration generation
- ✅ A clean, simple API for specifying externals
- ✅ Easy customization without repeating boilerplate
- ✅ CLI packages with proper shebang injection
🔧 Extending the Configuration
Section titled “🔧 Extending the Configuration”You can extend the configuration for your specific needs:
Adding Custom Options
Section titled “Adding Custom Options”import { createTsupConfig } from '@jmlweb/tsup-config-base';
export default createTsupConfig({ external: ['vitest'], options: { minify: true, sourcemap: true, splitting: true, target: 'es2022', },});Overriding Defaults
Section titled “Overriding Defaults”import { createTsupConfig } from '@jmlweb/tsup-config-base';
export default createTsupConfig({ format: ['esm'], // ESM only dts: false, // Disable type declarations outDir: 'build', // Custom output directory});Externals Strategy
Section titled “Externals Strategy”When configuring external, include:
- Peer dependencies: Packages that consumers should install themselves
- Workspace dependencies: Internal
@jmlweb/*packages used viaworkspace:* - Optional dependencies: Packages that may or may not be present
// Example: ESLint config packageexport default createTsupConfig({ external: [ // Internal workspace dependency '@jmlweb/eslint-config-base-js', // Peer dependencies '@eslint/js', 'eslint', 'eslint-config-prettier', 'eslint-plugin-simple-import-sort', 'typescript-eslint', ],});📝 Usage with Scripts
Section titled “📝 Usage with Scripts”Add build scripts to your package.json:
{ "scripts": { "build": "tsup", "clean": "rm -rf dist", "prepublishOnly": "pnpm build" }}Then run:
pnpm build # Build the packagepnpm clean # Clean build output📋 Requirements
Section titled “📋 Requirements”- Node.js >= 18.0.0
- tsup >= 8.0.0
📦 Peer Dependencies
Section titled “📦 Peer Dependencies”This package requires the following peer dependency:
tsup(>=8.0.0)
🔗 Related Packages
Section titled “🔗 Related Packages”Internal Packages
Section titled “Internal Packages”@jmlweb/eslint-config-base- ESLint config for TypeScript projects@jmlweb/prettier-config-base- Prettier config for consistent formatting@jmlweb/tsconfig-base- TypeScript configuration@jmlweb/vitest-config- Vitest configuration for testing
External Tools
Section titled “External Tools”- tsup - Bundle TypeScript libraries with zero config
- esbuild - Extremely fast JavaScript bundler (used by tsup)
- TypeScript - JavaScript with syntax for types
- Rollup - Alternative bundler for complex configurations
🔄 Migration Guide
Section titled “🔄 Migration Guide”Upgrading to a New Version
Section titled “Upgrading to a New Version”> Note: If no breaking changes were introduced in a version, it’s safe to upgrade without additional steps.
No breaking changes have been introduced yet. This package follows semantic versioning. When breaking changes are introduced, detailed migration instructions will be provided here.
For version history, see the Changelog.
Need Help? If you encounter issues during migration, please open an issue.
📜 Changelog
Section titled “📜 Changelog”See CHANGELOG.md for version history and release notes.
📄 License
Section titled “📄 License”MIT