Criando package e gerando bundle de forma prática para o npm com rollup.js
Este artigo é uma pequena parte de um outro projeto em que estou trabalhando e que me chamou muita atenção de como é simples criar nossos próprios packages para o npm quando necessário e gerar um bundle de forma rápida e prática, sem ter que criar configurações mirabolantes. O grande ponto positivo de usar o rollup.js é que criaremos nosso bundles seguindo as especificações de módulos de grandes e consolidados frameworks no mercado como jQuery, Vue, React, etc.
Utilizando o rollup.js podemos criar módulos compatíveis com CJS, AMD e UMD. Mas antes de começarmos, vamos entender um pouco sobre essas especificações de módulos e quais as suas diferenças
AMD (Asynchronous Module Definition)
É basicamente um padrão adotado para se escrever JavaScript modular no browser. A ideia é que todo o código JavaScript da aplicação seja separado em módulos e carregados de forma assíncrona. É altamente flexível, pois permite que os módulos sejam quebrados em diversos arquivos e que um determinado módulo só funcione quando todas suas dependências estiverem carregadas. Para seu funcionamento é necessário que o código seja transpilado ou utilizando bibliotecas e carregadores , sendo o RequireJS e o Dojo as mais famosas e mais utilizadas.
Exemplo de um módulo em RequireJS retirado da documentação:
require(['jquery'], function( $ ) {
console.log( $ ) // OK
});
require(['jquery'], function( jq ) {
console.log( jq ) // OK
});
require(['jquery'], function( ) {
console.log( $ ) // UNDEFINED!
});
CJS (CommonJS)
CommonJS é um formato de módulos adotado para otimizar e padronizar as APIs JavaScript. A ideia é simplesmente especificar uma forma de declarar módulos do lado do servidor e criar códigos reutilizáveis. O principal objetivo do CommonJS é trabalhar do lado do servidor e ao contrário do AMD, tem outras implicações práticas, como leitura e escrita de arquivos por exemplo. A implementação do módulo é definida ao longo do arquivo e depois é disponibilizado para que outros módulos possam importar (exports e require).
Exemplo:
// calc.jsexports.sum = (firstNum, secondNum) => firstNum + secondNum
// app.jsconst calc = require('calc.js')
calc.sum(2, 2)
Com o node.js temos a opção de utilizar o module.exports.
UMD (Universal Module Definition)
É aqui que está o segredo da coisa. O UMD é responsável por fazer as verificações necessárias (para saber se o desenvolvedor está utilizando AMD, CJS ou os dois). A parte mais legal de tudo é que o rollup.js faz isso automaticamente para nós com uma simples configuração. Com apenas um comando nosso bundle é gerado e está pronto para trabalhar com qualquer tipo de aplicação, seja ela RequireJS(que utiliza AMD) ou que utilize apenas ES2015 com import e export por exemplo.
E porque não utilizar webpack?
O webpack é uma ferramenta voltada para uma configuração minuciosa de todo o projeto. Ele possui diversas funcionalidades e extensões para subir servidor de desenvolvimento, empacotar arquivos de estilo, gerar chunks dos bundles, entre outras que acabam fugindo do objetivo de gerar módulos simples e reutilizáveis para serem exportados. Basicamente o rollup é mais indicado para criar packages(é o que faremos nesse artigo) e o webpack para aplicações mais robustas.
Agora chega de conversa e vamos ver como tudo isso funciona na prática!
Vamos criar um projeto chamado my-calculator, que fará apenas um cálculo simples de exemplo:
Vamos entrar na pasta do nosso projeto e iniciar o npm:
Vamos abrir o nosso projeto no editor de textos e criar a estrutura de pastas necessária. Basicamente vamos precisar de dois diretórios: dist e src.
dist: Pasta onde ficarão os bundles gerados pelo rollup e que serão importados como módulos pela nossa aplicação.
src: Pasta onde ficarão os arquivos do nosso projeto que serão empacotados pelo rollup.
Deve ficar assim:
Agora vamos criar o nosso arquivo calculator.js dentro de src e criar dois métodos: sum e subtract:
Vamos fazer a instalação do rollup, que fará o build dos nossos módulos. Para instalar basta rodar o seguinte comando:
npm install --global rollup
Agora que já temos nossa calculadora configurada e o rollup instalado, vamos para as configurações do rollup. Primeiro vamos criar na raiz do nosso projeto um arquivo chamado rollup.config.js e dentro dele vamos adicionar as seguintes configurações:
input: É o arquivo de entrada que deve ser lido.
output: É neste passo que a mágica acontece, onde configuramos as preferências do nosso bundle. Vamos adicionar um nome ao nosso bundle, o destino dele e no formato vamos colocar ‘umd’, que é o formato global de importação de módulos que vimos nas explicações anteriores. O arquivo deve ficar assim:
Agora vamos no nosso package.json e adicionar o comando para gerar o nosso bundle. Na área de scripts vamos adicionar a chave build e dentro escrever o comando de configuração do rollup:
Vamos rodar o comando de build no cmd e verificar o resultado:
Se tudo der certo a mensagem acima deve ser exibida no console. Vamos verificar o conteúdo do arquivo gerado dentro de dist:
O resultado acima é o esperado, um módulo que seja compatível com qualquer tipo de padrão de desenvolvimento adotado, seja AMD ou Common.
Para testar nossa calculadora, vamos criar um arquivo app.js na raiz e importar a nossa calculadora:
Se exibirmos o conteúdo da calculadora no console veremos o seguinte:
A imagem acima mostra o módulo e seus métodos. Vamos testar a funcionalidade no nosso arquivo de testes:
Se rodarmos esse código no cmd teremos o seguinte resultado:
Agora que tudo está pronto, vamos preparar nosso projeto para subir para o npm. Para isso, precisamos fazer algumas configurações no package.json:
Mudar o main para dist/calculator.js.
Criar uma chave files em que devem ser especificados todos os arquivos que devem ser mandados para o npm. Neste caso, vamos enviar todos os arquivos dos diretórios dist e src.
Aproveitei também para adicionar as urls do repositório do git.
Tudo já está configurado e para subir nossa calculadora no npm, basta rodar os comandos listados abaixo.
Se você não tiver uma conta, basta se cadastrar pelo comando:
npm adduser
Se já possuir uma conta é só fazer login pelo comando:
npm login
O prompt irá pedir suas credenciais.
Depois de logado basta digitar npm publish e pronto! Seu pacote foi enviado com sucesso para sua conta do npm e está disponível para ser baixado em qualquer projeto nodejs.
Para testar seu pacote, basta instalá-lo em um outro projeto que utilize nodejs e verificar seus arquivos dentro da pasta node_modules.
Para instalar use o nome que você deu a seu pacote, neste caso é my-calculator-calc
npm install my-calculator-calc
Conclusão
O rollup é uma ferramenta muito útil, mas é importante deixar claro que este artigo explorou suas funcionalidades mais básicas. Existe uma infinidade de dependências e opções que podem ser utilizadas, dependendo das necessidades do seu projeto. Mas o ponto principal é a facilidade que essa ferramenta nos traz e que a utilizando estamos seguindo os padrões da comunidade e de grandes frameworks do mercado.
Referências
Documentação do rollup: https://rollupjs.org/guide/en.
Documentação do RequireJS: https://requirejs.org/
Writing Modular JavaScript With AMD, CommonJS & ES Harmony: https://addyosmani.com/writing-modular-js/