DEV Community

Marcelo Lourenço
Marcelo Lourenço

Posted on • Edited on • Originally published at Medium

1

Criando um Pacote NPM com Suporte a CommonJS e ESM usando Rollup

Neste post, vamos explorar como criar um pacote NPM com suporte a CommonJS (CJS) e ECMAScript Modules (ESM) usando Rollup.

Rollup é um bundler JavaScript ideal para criar bibliotecas e pacotes, pois ele gera bundles de código altamente otimizados, que podem ser facilmente usados em diferentes ambientes.

Estrutura do projeto:

my-npm-package/
├── src/
│   ├── index.js
|   └── utils
|       ├──math.js
|       └──string.js
├── rollup.config.js
└── package.json
Enter fullscreen mode Exit fullscreen mode

1. Configurando o Projeto

Comece criando um novo diretório para o seu pacote NPM. Dentro do diretório, execute o comando:

npm init -y
Enter fullscreen mode Exit fullscreen mode

Isso irá gerar um arquivo package.json básico.

Atualize o arquivo package.json com as seguintes informações:

{
  "name": "my-npm-package",
  "version": "1.0.0",
  "description": "",
  "type": "module",
  "main": "dist/index.cjs",
  "module": "dist/index.mjs",
  "scripts": {
    "build": "rollup -c",
    "dev": "rollup -c --watch"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/your-username/my-npm-package.git"
  },
  "author": "",
  "license": "MIT"
}
Enter fullscreen mode Exit fullscreen mode

Explicando as propriedades:

  • name: Nome do pacote NPM.
  • version: Versão do pacote.
  • description: Descrição do pacote.
  • main: Define o arquivo principal para projetos CommonJS.
  • module: Define o arquivo principal para projetos ESM.
  • scripts: Define scripts para build e desenvolvimento.
  • repository: Define o repositório do pacote.
  • author: Nome do autor do pacote.
  • license: Licença do pacote.

Em seguida, instale as dependências necessárias:

npm install rollup @rollup/plugin-commonjs @rollup/plugin-node-resolve
Enter fullscreen mode Exit fullscreen mode

Explicando as dependências:

  • rollup: Ferramenta de empacotamento de módulos.
  • rollup-plugin-commonjs: Plugin Rollup para lidar com módulos CommonJS.
  • rollup-plugin-node-resolve: Plugin Rollup para resolver dependências de módulos do Node.js.

2. Criando a Pasta src

Crie uma pasta chamada src dentro do diretório do projeto.

Dentro de src, crie um arquivo index.js.

// src/index.js
import { add } from './utils/math.js';
import { toUpperCase } from './utils/string.js';

export function calculate() {
  const result = add(10, 20);
  return `Result: ${result}, UpperCase: ${toUpperCase('hello')}`;
}
Enter fullscreen mode Exit fullscreen mode

Dentro de src, crie o subdiretório utils.

Dentro do subdiretório utils, crie os aquivos:
math.js

// src/utils/math.js
export function add(a, b) {
  return a + b;
}
Enter fullscreen mode Exit fullscreen mode

string.js

// src/utils/string.js
export function toUpperCase(str) {
  return str.toUpperCase();
}
Enter fullscreen mode Exit fullscreen mode

3. Criando o Arquivo rollup.config.js.

Crie um arquivo rollup.config.js com a configuração do Rollup.

O Rollup tem 2 opções de configurações de saída:

  • A primeira: Todo o código em único arquivo de saída.
  • A segunda: Utilizando o preserveModules para manter a estrutura de módulos.

3.1 Arquivo rollup.config.js sem preservar a estrutura de módulo

O Rollup, por padrão, combina todos os módulos em um único arquivo de saída. Isso significa que todos os seus módulos, incluindo seus próprios e seus dependentes, são mesclados em um único arquivo JavaScript.

// rollup.config.js
import commonjs from 'rollup-plugin-commonjs';
import resolve from 'rollup-plugin-node-resolve';

export default [
  {
    input: 'src/index.js', // Arquivo principal de entrada
    output: {
      file: 'dist/index.cjs', // Diretório de saída para CommonJS
      format: 'cjs',
      sourcemap: true,
    },
    plugins: [
      resolve(),
      commonjs(),
    ],
  },
  {
    input: 'src/index.js', // Arquivo principal de entrada
    output: {
      file: 'dist/index.mjs', // Diretório de saída para ES Modules
      format: 'es',
      sourcemap: true,
    },
    plugins: [
      resolve(),  // Resolve módulos de node_modules
      commonjs()  // Converte pacotes CommonJS para ESModules
    ],
  },
];
Enter fullscreen mode Exit fullscreen mode

Explicando as configurações:

  • input: Define o arquivo de entrada para o Rollup.
  • output: Define o arquivo de saída e o formato de saída.
  • format: Define o formato do módulo (ESM ou CommonJS).
  • plugins: Define os plugins que serão utilizados no Rollup.

3.2 Arquivo rollup.config.js preservando a estrutura de módulo

O Rollup mantém a estrutura de módulos do seu código original. Cada módulo do seu projeto será empacotado em seu próprio arquivo.

// rollup.config.js
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';

export default {
  input: './src/index.js',  // Arquivo principal de entrada

  output: [
    {
      dir: 'dist/cjs', // Diretório de saída para CommonJS
      format: 'cjs',
      entryFileNames: '[name].cjs', // Mantém o nome do arquivo original
      exports: 'auto',
      preserveModules: true, // Preserva a estrutura dos módulos
      preserveModulesRoot: 'src', // Diretório base que será mantido
    },
    {
      dir: 'dist/mjs', // Diretório de saída para ES Modules
      format: 'es',
      entryFileNames: '[name].mjs',
      preserveModules: true,
      preserveModulesRoot: 'src',
    }
  ],
  plugins: [
    resolve(),  // Resolve módulos de node_modules
    commonjs()  // Converte pacotes CommonJS para ESModules
  ]
};
Enter fullscreen mode Exit fullscreen mode

Explicando as configurações:

  • entryFileNames: Define um padrão para os nomes dos arquivos de saída, usando placeholders:
    • [name]: Substituído pelo nome do módulo.
    • [hash]: Substituído por um hash único para o arquivo.
    • [format]: Substituído pelo formato do módulo (esm ou cjs).
  • preserveModules: Preserva a estrutura de módulos original do código. Se true, cada módulo será empacotado em seu próprio arquivo.
  • preserveModulesRoot: Define o diretório raiz dos módulos a serem preservados.

3.2.1 Neste caso, altere essas linhas no package.json:

"main": "dist/cjs/index.cjs",
"module": "dist/mjs/index.mjs",
Enter fullscreen mode Exit fullscreen mode

4. Compilando e Publicando o Pacote

Execute o comando npm run build para compilar o seu pacote. Isso irá gerar os arquivos compilados em dist/.

Em seguida, publique o pacote no npm usando o comando npm publish.

5. Usando o Pacote

Agora você pode usar o pacote NPM que criou em outros projetos.

  • Exemplo em um projeto CommonJS:
const { calculate } = require('my-npm-package');
console.log(calculate()); // "Result: 30, UpperCase: HELLO"
Enter fullscreen mode Exit fullscreen mode
  • Exemplo em um projeto ESM (quando o package.json tem o "type": "module"):
import { calculate } from 'my-npm-package';
console.log(calculate()); // "Result: 30, UpperCase: HELLO"
Enter fullscreen mode Exit fullscreen mode

Conclusão

Criar um pacote NPM com suporte a CommonJS e ESM é simples usando o Rollup. Ao seguir as etapas descritas neste post, você pode construir um pacote flexível e reutilizável que atenda às necessidades de diferentes projetos.

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

Top comments (0)

Heroku

Build apps, not infrastructure.

Dealing with servers, hardware, and infrastructure can take up your valuable time. Discover the benefits of Heroku, the PaaS of choice for developers since 2007.

Visit Site

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay