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
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
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"
}
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
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')}`;
}
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;
}
string.js
// src/utils/string.js
export function toUpperCase(str) {
return str.toUpperCase();
}
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
],
},
];
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
]
};
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",
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"
-
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"
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.
Top comments (0)