O tsdown no Node.js é um bundler voltado à criação de bibliotecas TypeScript e JavaScript. Ele usa Rolldown como motor, oferece configuração enxuta e inclui recursos comuns para autores de pacotes, como geração de declarations, múltiplos formatos, sourcemaps, tree shaking e validação de exports.
A proposta é reduzir a quantidade de plugins e scripts necessários para publicar uma biblioteca. Porém, o autor continua responsável por definir a API pública, externalizar dependências, testar ESM e CommonJS, inspecionar o tarball e verificar tipos.
Neste guia, você aprenderá a instalar tsdown, configurar entry points, gerar ESM e CJS, criar arquivos .d.ts, controlar dependências, usar watch mode, validar o pacote e integrar o build ao CI.
O que é tsdown?
A documentação oficial do tsdown apresenta a ferramenta como um bundler de bibliotecas construído sobre Rolldown. Ele oferece defaults para pacotes e suporte a:
- TypeScript e JavaScript;
- declarations;
- ESM, CommonJS, IIFE e UMD;
- JSON e WASM;
- tree shaking;
- minificação;
- sourcemaps;
- plugins Rolldown e parte do ecossistema Rollup.
Instalação
npm install --save-dev tsdown typescriptFixe a versão no lockfile e faça upgrades em pull requests dedicados.
Primeiro build
npx tsdown src/index.tsO comando gera o output conforme defaults e o package.json. Para um projeto real, crie configuração explícita.
Arquivo de configuração
Crie tsdown.config.ts:
import { defineConfig } from 'tsdown';
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm'],
dts: true,
sourcemap: true,
clean: true
});Script no package.json
{
"scripts": {
"build": "tsdown",
"build:watch": "tsdown --watch",
"typecheck": "tsc --noEmit",
"prepack": "npm run typecheck && npm test && npm run build"
}
}Veja npm Scripts no Node.js.
Gerando ESM
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm'],
outDir: 'dist',
dts: true
});No package.json:
{
"type": "module",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
}
}
}Consulte TypeScript ESM no Node.js.
ESM e CommonJS
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
sourcemap: true
});O package.json pode mapear:
{
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"require": "./dist/index.cjs"
}
}
}Teste os dois formatos para evitar diferenças de instância e interop.
Múltiplos entry points
export default defineConfig({
entry: {
index: 'src/index.ts',
errors: 'src/errors.ts',
testing: 'src/testing.ts'
},
format: ['esm'],
dts: true
});Defina os subpaths:
{
"exports": {
".": "./dist/index.js",
"./errors": "./dist/errors.js",
"./testing": "./dist/testing.js"
}
}Veja Exports e Imports no package.json.
Declarations TypeScript
dts: truetsdown gera arquivos .d.ts, mas o typecheck continua necessário:
npm run typecheckConfirme que todos os exports públicos aparecem nos tipos e que referências internas não escapam.
tsconfig
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "Bundler",
"strict": true,
"declaration": true,
"skipLibCheck": true
},
"include": ["src"]
}Para aplicações executadas diretamente com tsc, use NodeNext; para um bundler que resolve e reescreve imports, Bundler pode ser apropriado.
Dependências externas
Bibliotecas não devem incorporar peer dependencies:
export default defineConfig({
entry: ['src/index.ts'],
external: ['react', 'fastify']
});Subpaths também precisam ficar externos. Use uma função quando necessário.
Dependencies e peerDependencies
A ferramenta pode tratar dependências com defaults próprios, mas revise o output. Bibliotecas pequenas podem incorporar utilitários internos; frameworks e runtimes compartilhados devem permanecer externos.
{
"peerDependencies": {
"fastify": "^5.0.0"
}
}noExternal
Use noExternal para forçar uma dependência no bundle:
noExternal: ['small-runtime-helper']Confirme licença, tamanho e comportamento.
Target
target: 'node22'O target controla sintaxe emitida. Alinhe ao campo engines:
{
"engines": {
"node": ">=22"
}
}Platform
platform: 'node'Para bibliotecas universais, evite importar módulos como node:fs no entry point principal.
Tree shaking
tsdown remove código não utilizado quando a análise permite. Evite side effects no import e prefira exports nomeados.
{
"sideEffects": false
}Não use esse campo se módulos registram hooks, importam CSS ou executam inicialização.
Unbundle
Uma biblioteca pode preservar mais arquivos em vez de produzir um único bundle:
unbundle: trueEsse modo facilita debugging e subpaths, mas aumenta a quantidade de artefatos. Inspecione a estrutura final.
Sourcemaps
sourcemap: trueSourcemaps ajudam consumidores a depurar. Avalie se fontes devem ser incluídas e proteja código sensível.
Minificação
minify: truePacotes Node.js geralmente não precisam ser minificados. Código legível oferece stacks melhores e permite que o consumidor otimize o conjunto final.
Cleaning
clean: trueLimpar o diretório evita arquivos antigos que não correspondem mais aos exports. Não aponte outDir para uma pasta com arquivos manuais.
Watch mode
npx tsdown --watchUse durante desenvolvimento com uma aplicação consumidora. Mudanças no package.json ou configuração podem exigir reinício.
Executáveis
Para CLIs, preserve shebang e configure bin:
{
"bin": {
"my-cli": "./dist/cli.js"
}
}Teste permissão executável no tarball.
Package exports automáticos
tsdown possui recursos para gerar ou validar exports. Use como ajuda, mas revise o contrato final. Remover um subpath é breaking change.
Validação do pacote
Ferramentas como publint e Are the Types Wrong podem encontrar problemas de exports e tipos. Quando habilitadas pelo tsdown, ainda revise o resultado.
npm pack --dry-runTestando o tarball
npm run build
npm pack
mkdir /tmp/consumer
cd /tmp/consumer
npm init -y
npm install /caminho/pacote-1.0.0.tgzTeste ESM:
node --input-type=module -e "import('pacote').then(console.log)"Teste CommonJS:
node -e "console.log(require('pacote'))"Consulte Publicar Pacote no npm.
Plugins
tsdown suporta plugins Rolldown e muitos plugins Rollup. Cada plugin executa código durante build. Fixe versões e use apenas quando necessário.
Hooks
Hooks podem copiar arquivos, validar output ou gerar metadata. Mantenha-os pequenos e determinísticos.
CSS e assets
Bibliotecas de UI podem processar CSS e assets. Exporte o arquivo CSS:
{
"exports": {
".": "./dist/index.js",
"./style.css": "./dist/style.css"
}
}WASM
O suporte a WASM depende da configuração e destino. Teste em Node.js e bundlers consumidores. Não assuma que um caminho relativo funciona após publicação.
Migração do tsup
tsdown oferece uma experiência semelhante ao tsup. Migre:
- liste entry points e formatos;
- replique external;
- configure dts;
- compare nomes dos arquivos;
- teste exports;
- instale o tarball;
- compare tamanho e runtime.
Comparação com Rollup
Rollup para Bibliotecas Node.js oferece configuração detalhada e ecossistema consolidado. tsdown fornece defaults de biblioteca e velocidade do Rolldown.
Comparação com esbuild
esbuild no Node.js é simples e rápido para aplicações e ferramentas. tsdown adiciona recursos de pacote como declarations e validação.
CI
- run: npm ci
- run: npm run lint
- run: npm run typecheck
- run: npm test
- run: npm run build
- run: npm pack --dry-runConsulte CI para Node.js com GitHub Actions.
Segurança
- Fixe versões.
- Revise plugins.
- Não incorpore segredos.
- Restrinja
files. - Valide exports.
- Teste o tarball.
- Proteja sourcemaps.
- Publique com OIDC.
Erros comuns
- Peer dependency no bundle: duas instâncias aparecem.
- Types divergentes: runtime funciona e TypeScript falha.
- Exports não testados: consumidores não importam.
- Target muito novo: Node.js antigo quebra.
- Minificar sem necessidade: stacks pioram.
- Plugin não confiável: supply chain cresce.
- Arquivos antigos em dist: pacote contém artefatos inválidos.
- Teste só no monorepo: links locais escondem falhas.
Configuração recomendada
import { defineConfig } from 'tsdown';
export default defineConfig({
entry: {
index: 'src/index.ts',
errors: 'src/errors.ts'
},
format: ['esm'],
platform: 'node',
target: 'node22',
dts: true,
sourcemap: true,
clean: true,
external: ['fastify'],
minify: false
});Conclusão
O tsdown no Node.js simplifica o build de bibliotecas ao combinar Rolldown, declarations, formatos e validação de pacote. A configuração pequena permite criar outputs modernos sem montar um pipeline extenso.
Externalize dependências compartilhadas, mantenha typecheck, defina exports e teste o tarball. Com CI e versionamento fixo, tsdown oferece velocidade sem transformar defaults em um contrato não revisado.


