Home > Blog > Desenvolvimento Web
Desenvolvimento Web
JavaScript
Programação

Rollup para Bibliotecas Node.js

Atualizado em: 11 de setembro de 2026

Estação de trabalho usada no desenvolvimento de aplicações Node.js

O Rollup para bibliotecas Node.js é uma opção madura para gerar pacotes ESM e CommonJS, aplicar tree shaking, preservar módulos e controlar entry points públicos. Diferente de um build focado apenas em aplicações, uma biblioteca precisa cuidar de exports, peer dependencies, declarations TypeScript, compatibilidade e tamanho entregue aos consumidores.

Rollup analisa o grafo de módulos, remove código não utilizado quando possível e oferece uma API de plugins extensa. Porém, bundlar tudo nem sempre é desejável: dependências externas, módulos nativos e subpaths públicos precisam permanecer coerentes com o package.json.

Neste guia, você aprenderá a configurar Rollup para bibliotecas Node.js, gerar ESM e CJS, marcar dependências externas, compilar TypeScript, preservar módulos, criar sourcemaps, publicar tipos e testar o tarball.

Instalação

npm install --save-dev rollup

Para TypeScript e resolução de pacotes:

npm install --save-dev \
  @rollup/plugin-node-resolve \
  @rollup/plugin-commonjs \
  @rollup/plugin-typescript \
  typescript \
  tslib

Primeiro arquivo de configuração

Crie rollup.config.mjs:

import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import typescript from '@rollup/plugin-typescript';

export default {
  input: 'src/index.ts',
  plugins: [
    resolve(),
    commonjs(),
    typescript({ tsconfig: './tsconfig.build.json' })
  ],
  output: [
    {
      file: 'dist/index.js',
      format: 'es',
      sourcemap: true
    },
    {
      file: 'dist/index.cjs',
      format: 'cjs',
      sourcemap: true,
      exports: 'named'
    }
  ]
};

A documentação oficial de opções de configuração do Rollup detalha input, external, outputs, plugins, preserveModules e tree shaking.

Script de build

{
  "scripts": {
    "build": "rollup --config",
    "build:watch": "rollup --config --watch",
    "typecheck": "tsc --noEmit"
  }
}

Veja npm Scripts no Node.js.

Package.json da biblioteca

{
  "name": "@empresa/domain",
  "version": "1.0.0",
  "type": "module",
  "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"
    }
  },
  "files": ["dist"]
}

O artigo Exports e Imports no package.json explica o contrato público.

Dependências externas

Bibliotecas geralmente não devem incorporar todas as dependências. Peer dependencies precisam permanecer externas:

external: [
  'react',
  'fastify',
  /^node:/
]

Uma função pode usar o package.json:

import pkg from './package.json' with { type: 'json' };

const externalPackages = new Set([
  ...Object.keys(pkg.dependencies ?? {}),
  ...Object.keys(pkg.peerDependencies ?? {})
]);

export default {
  external(id) {
    return id.startsWith('node:') ||
      [...externalPackages].some(name =>
        id === name || id.startsWith(`${name}/`)
      );
  }
};

Decida se dependencies devem ser bundladas ou externas conforme o produto. Para SDKs, externas preservam deduplicação; para CLIs, bundle pode simplificar distribuição.

Peer dependencies

{
  "peerDependencies": {
    "fastify": "^5.0.0"
  }
}

Declare apenas versões testadas. Não inclua Fastify no bundle de um plugin, pois o consumidor deve fornecer a instância compatível.

TypeScript e declarations

O plugin transforma TypeScript, mas a geração de tipos precisa ser verificada:

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "strict": true,
    "declaration": true,
    "declarationDir": "dist/types",
    "sourceMap": true,
    "rootDir": "src"
  }
}

Para controlar melhor, gere declarations em etapa separada:

tsc --emitDeclarationOnly -p tsconfig.types.json

Depois copie ou agrupe os tipos para corresponder aos exports.

Typecheck separado

Não trate o plugin TypeScript como única validação:

npm run typecheck
npm run build

O CI deve executar ambos. Consulte CI para Node.js com GitHub Actions.

Múltiplos entry points

input: {
  index: 'src/index.ts',
  errors: 'src/errors.ts',
  testing: 'src/testing.ts'
},
output: {
  dir: 'dist',
  format: 'es',
  entryFileNames: '[name].js',
  sourcemap: true
}

No package.json:

{
  "exports": {
    ".": "./dist/index.js",
    "./errors": "./dist/errors.js",
    "./testing": "./dist/testing.js"
  }
}

Preserve modules

output: {
  dir: 'dist',
  format: 'es',
  preserveModules: true,
  preserveModulesRoot: 'src'
}

Essa opção mantém arquivos separados, facilitando imports por subpath e tree shaking do consumidor. Porém, plugins podem gerar módulos virtuais e nomes inesperados. A documentação recomenda considerar múltiplos entry points quando você quer preservar uma estrutura pública controlada.

Tree shaking

Rollup remove exports não utilizados quando consegue provar que não possuem efeitos colaterais. Código dinâmico, CommonJS e propriedades acessadas podem reduzir a eficiência.

treeshake: {
  moduleSideEffects: false
}

Não defina moduleSideEffects: false se módulos executam registro, polyfill, CSS ou inicialização ao importar. Uma configuração errada remove comportamento necessário.

Side effects no package.json

{
  "sideEffects": false
}

Esse campo é consumido por bundlers, não apenas Rollup. Só use quando todos os módulos podem ser removidos sem alterar comportamento.

CommonJS

O plugin CommonJS converte dependências que usam require:

commonjs({
  include: /node_modules/
})

Evite aplicar transformação a todo o projeto sem necessidade. ESM nativo produz análise melhor.

node-resolve

resolve({
  exportConditions: ['node'],
  preferBuiltins: true
})

preferBuiltins ajuda a usar módulos nativos. Confirme condições de exports para o runtime.

Interop

Ao gerar CommonJS, imports default de dependências externas podem exigir helpers:

output: {
  format: 'cjs',
  interop: 'auto'
}

Teste dependências CommonJS reais. O comportamento de Rollup pode diferir do esModuleInterop do TypeScript.

Sourcemaps

sourcemap: true,
sourcemapExcludeSources: true

Publique sourcemaps apenas se fizer sentido. Eles melhoram debug, mas podem expor código-fonte.

Minificação

import terser from '@rollup/plugin-terser';

output: {
  file: 'dist/index.min.js',
  format: 'es',
  plugins: [terser()]
}

Bibliotecas normalmente não precisam ser minificadas; o consumidor pode aplicar sua própria estratégia. Minificação também prejudica stacks e auditoria.

Assets e plugins

Plugins conseguem emitir arquivos com this.emitFile. Use para schemas, WASM ou templates necessários. Garanta que todos os assets sejam incluídos no tarball.

Watch mode

npm run build:watch

Rollup reutiliza cache para acelerar rebuilds. Evite escrever output dentro da pasta observada sem configuração apropriada.

Warnings como erros

onLog(level, log, handler) {
  if (level === 'warn') {
    handler('error', log);
    return;
  }
  handler(level, log);
}

Alguns warnings, como dependências circulares conhecidas, podem ser tratados explicitamente. Não ignore todos indiscriminadamente.

Dependências circulares

Um ciclo não é automaticamente bug, mas pode causar valores parcialmente inicializados e dificultar tree shaking. Use warnings para revisar arquitetura.

Bundle de CLI

Para uma CLI Node.js:

output: {
  file: 'dist/cli.js',
  format: 'es',
  banner: '#!/usr/bin/env node'
}

No package.json:

{
  "bin": {
    "minha-cli": "./dist/cli.js"
  }
}

Garanta permissão executável no pacote.

Build dual ESM e CJS

Dois outputs são simples quando o código é puro, mas tipos e exports precisam ser coerentes. Teste:

node --input-type=module -e "import('@empresa/domain').then(console.log)"
node -e "console.log(require('@empresa/domain'))"

Evite estado global duplicado entre os formatos.

Teste do tarball

npm pack --dry-run
npm pack

Instale em projetos consumidores ESM, CommonJS e TypeScript. Veja Publicar Pacote no npm.

Comparação com esbuild

Rollup oferece controle detalhado de chunks, plugins e bibliotecas. esbuild prioriza velocidade e simplicidade. Consulte esbuild no Node.js. Escolha com base em formato, plugins, declarations e desempenho real.

CI

- run: npm ci
- run: npm run lint
- run: npm run typecheck
- run: npm test
- run: npm run build
- run: npm pack --dry-run

Armazene o tarball como artifact e execute testes de instalação antes de publicar.

Segurança

  • Fixe versões de plugins.
  • Revise código executado no build.
  • Não incorpore segredos.
  • Restrinja arquivos publicados.
  • Teste peer dependencies.
  • Proteja sourcemaps.
  • Use OIDC na publicação.

Erros comuns

  • Bundlar peer dependency: consumidor recebe duas instâncias.
  • Tipos fora dos exports: editor falha.
  • Side effects falsos: código necessário é removido.
  • CJS sem interop testado: import default quebra.
  • PreserveModules sem revisar: internals são publicados.
  • Minificar biblioteca: diagnóstico piora.
  • Tarball não testado: arquivos faltam.
  • Plugin não confiável: supply chain aumenta.

Configuração recomendada

import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import typescript from '@rollup/plugin-typescript';

export default {
  input: {
    index: 'src/index.ts',
    errors: 'src/errors.ts'
  },
  external: id => id.startsWith('node:') ||
    id === 'fastify' || id.startsWith('fastify/'),
  plugins: [
    resolve({ preferBuiltins: true }),
    commonjs(),
    typescript({ tsconfig: './tsconfig.build.json' })
  ],
  output: {
    dir: 'dist',
    format: 'es',
    entryFileNames: '[name].js',
    sourcemap: true
  }
};

Conclusão

O Rollup para bibliotecas Node.js oferece controle sobre exports, tree shaking, múltiplos entry points e formatos de saída. O maior valor aparece quando o build preserva o contrato público e mantém dependências corretas fora do bundle.

Gere declarations separadas, teste ESM e CommonJS, inspecione o tarball e execute CI completa. Com external, exports e side effects bem definidos, Rollup produz bibliotecas previsíveis para consumidores Node.js.

10 melhores cursos de programação em 2026

Descubra os melhores cursos de programação. Aprenda a escolher o curso ideal para iniciar ou avançar na carreira de desenvolvedor

POSTS RELACIONADOS

Ver todos

Seta para a direita