tsup es un empaquetador para librerías TypeScript construido sobre esbuild. Con una única herramienta genera los formatos ESM y CommonJS, los ficheros de declaración .d.ts y los source maps, sin necesidad de configurar Rollup ni de encadenar llamadas a tsc.
Instalación y uso básico
// Instalación:
// npm install --save-dev tsup
// package.json
{
"scripts": {
"build": "tsup",
"dev": "tsup --watch"
}
}
// tsup.config.ts
import { defineConfig } from 'tsup';
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
sourcemap: true,
clean: true,
});
El comando tsup sin argumentos busca tsup.config.ts en la raíz del proyecto. Con la config anterior genera:
// dist/ // index.js (ESM) // index.cjs (CommonJS) // index.d.ts (declaraciones de tipos) // index.js.map (source maps) // index.cjs.map
Entry points múltiples
Las librerías con sub-rutas de importación necesitan múltiples puntos de entrada:
// tsup.config.ts
import { defineConfig } from 'tsup';
export default defineConfig({
entry: {
index: 'src/index.ts',
utils: 'src/utils.ts',
'react/index': 'src/react/index.ts',
},
format: ['esm', 'cjs'],
dts: true,
sourcemap: true,
clean: true,
splitting: true, // Code splitting para ESM (código compartido en chunks)
});
El campo exports de package.json
Con múltiples entry points, el package.json necesita el campo exports para que los bundlers y Node.js resuelvan correctamente las sub-rutas:
// package.json
{
"name": "mi-libreria",
"version": "1.0.0",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"import": { "types": "./dist/index.d.ts", "default": "./dist/index.js" },
"require": { "types": "./dist/index.d.cts", "default": "./dist/index.cjs" }
},
"./utils": {
"import": { "types": "./dist/utils.d.ts", "default": "./dist/utils.js" },
"require": { "types": "./dist/utils.d.cts", "default": "./dist/utils.cjs" }
}
},
"files": ["dist"]
}
Minificación y opciones avanzadas
// tsup.config.ts
import { defineConfig } from 'tsup';
export default defineConfig([
// Compilación de desarrollo (rápida, con source maps):
{
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
sourcemap: true,
},
// Compilación de producción (minificada):
{
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
minify: true,
outExtension: ({ format }) => ({
js: format === 'esm' ? '.min.js' : '.min.cjs',
}),
},
]);
tsup frente a otras herramientas
tsc: genera declaraciones de tipos y transpila, pero no hace bundle ni tree-shaking. Buena opción si solo necesitas CommonJS y el proyecto tiene pocas dependencias externas.
esbuild directamente: muy rápido, pero no genera .d.ts. Hay que combinarlo con tsc --emitDeclarationOnly.
Rollup: más configurable, mejor tree-shaking, pero requiere bastantes plugins para TypeScript (rollup-plugin-typescript2 o @rollup/plugin-typescript más dts-bundle-generator). Tiene sentido para librerías con requisitos muy específicos de bundle.
tsup: la opción con mejor relación configuración/potencia para la mayoría de librerías TypeScript. Cubre el 95% de los casos con configuración mínima.
Imagen: Pexels / Bibek Ghosh
