Introdução ao gerenciador de pacotes do JavaScript - NPM

Introdução ao gerenciador de pacotes do JavaScript - NPM

O que são pacotes?

Na profissão de Engenheiro de Software é costumeiro reutilizar código de outros programadores e nem me refiro a trabalhar em um projeto já escrito por um de seus colegas de trabalho, mas sim da utilização das famosas bibliotecas/pacotes/frameworks.

Imagine se todo código de uma biblioteca que você quisesse usar precisasse ser copiado manualmente para o seu projeto, isto é, manualmente copiar arquivo a arquivo para que as funções possam ser chamadas. Que pesadelo seria fazer isso considerando ainda que essas bibliotecas podem conter até centenas de arquivos e afins.

É aqui que entram as bibliotecas: são um conjunto de software facilmente instalável que resolvem um problema geralmente comum. Por exemplo: a biblioteca cheerio que é responsável por prover uma API que parseia código HTML, permitindo que o desenvolvedor o manipule facilmente. Ela é vastamente usada para fazer leitura de dados que foram adquiridos por scrapers.

Simplificando a vida com gerenciador de pacotes

Agora vamos pensar: como atualizar estes pacotes manualmente? Muitas vezes eles são dependentes uns dos outros e uma simples atualização pode acabar quebrando todos os outros pacotes. Uma das responsabilidades comuns de gerenciadores de pacotes é exatamente isso: atualizar dependências. Algumas outras funcionalidades:

  • Certificar-se que os pacotes foram baixados sem erros
  • Verificar a origem dos pacotes através da assinatura digital (PKI)
  • Gerir dependências e evitar o inferno de dependências, isto é, se certificar que todos os pacotes que uma dependência x precisa serão instalados previamente.
  • Publicar pacotes para que outros desenvolvedores consigam instalar facilmente

A fim de comparação com nosso primeiro cenário, fomos de precisar importar third party software manualmente para um app para os gerenciadores de pacotes, que fazem toda a gestão da complexidade em relação a dependências e essas funcionalidades estão ao nosso alcance através de alguns comandos no terminal.

NPM - O maior software registry existente

Em diferentes linguagens de programação e até em distintos sistemas operacionais temos gerenciadores de pacotes específicos. Alguns exemplos:

  • Maven para projetos em Java, entre outras linguagens.
  • Pip para projetos em Python.
  • Go modules em Golang.
  • Brew para Mac.
  • Chocolatey para Windows.

Cada um destes softwares tem suas particularidades. O maven, por exemplo, além de fazer o que citamos anteriormente quando falamos das funcionalidades dos gerenciadores, também cuida do build, reports, releases. Se tornou um modelo, um esqueleto para suas aplicações.

Para aplicações escritas em JavaScript temos o NPM - node package manager. Ele é o maior repositório de código de uma única linguagem existente ( a marca de possuir mais de um milhão de pacotes foi ultrapassada).

O criador do NPM é o Isaac Z. Schlueter, hoje é o CEO da NPM Inc. O gerenciador de pacotes foi criado com a intenção de seu criador em gerenciar seus próprios pacotes quando ele trabalhava no Yahoo, isso em 2009. Mas foi no início de 2010 que a primeira versão útil estava disponível a seus usuários.

O NPM além de ser um gerenciador de pacotes com as funcionalidades que já explicamos anteriormente como: gerir dependências, permitir a publicação de pacotes, também é uma ferramenta de CLI (command line interface). Isto é, ele também permite a criação e gerenciamento de pacotes através da linha de comando usando a keyword npm. Uma outra funcionalidade disponível é o controle da aplicação com o comando npm run, que falaremos mais abaixo a respeito.

A estrutura do package.json

Para fazer o uso do NPM com seu projeto é necessário um arquivo chamado package.json. Veja o exemplo abaixo:

{
  "name": "nodejs-api-template",
  "version": "1.0.0",
  "description": "",
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "body-parser": "^1.18.3",
    "consign": "^0.1.6",
    "cors": "^2.8.4",
    "express": "^4.16.3",
    "express-validator": "^5.2.0",
    "helmet": "^3.21.3"
  }
}
 


Vamos fazer um breakdown das propriedades acima:

  • version: indica a versão atual da sua aplicação
  • name:  nome de sua aplicação
  • description: descrição de seu app
  • main: entry point de seu app
  • private: caso seja verdadeiro impede que seja publicado acidentalmente como público no diretório da NPM
  • scripts: seta um lista de scripts que podem ser rodados
  • dependencies: a lista de todas as dependências que são necessárias para que seu app rode corretamente.

As dependências aqui podem ser destacadas como uma das principais partes do arquivo package.json. São as informações guardadas nessa palavra chave que permitem que todas as dependências necessárias para o funcionamento correto de um app X sejam instaladas. Note que as versões também são especificadas, afinal no dado aplicativo pode ser que uma variante específica seja obrigatória. Vamos falar adiante a respeito do comando npm install, que faz a instalação das dependências de forma automática, facilitando o desenvolvimento e compartilhando das aplicações.

NPM na prática

Para realizar a instalação no NPM, siga os passos para a instalação no NodeJS, disponíveis no próprio site do Node.

Vamos falar dos comandos essenciais para utilizar a ferramenta. Esses comandos devem ser utilizados no terminal de seu sistema operacional e fazem parte da CLI do NPM. Começaremos do início, shall we? Com o npm init:

  1. O npm init é um comando irá iniciar um guia passo a passo para que você possa configurar o seu projeto NPM, as seguintes opções irão aparecer:
  • Nome do projeto;
  • Versão inicial;
  • Descrição;
  • Entry point: já falamos dele anteriormente. Seria o arquivo principal do app;
  • Test command;
  • Git repository: repositório onde o projeto pode ser encontrado;
  • Project keywords: palavras chaves relacionadas ao projeto;
  • Licença.

É importante mencionar que caso você não queira preencher alguma informação uma dica será mostrada e você pode apenas pressionar enter para aceita-la. No fim deste processo o arquivo package.json será criado.

Exemplo de um pacote sendo criado:

  1. Um outro comando que é de extrema importância para usar em qualquer gerenciador de dependências é o que possui a finalidade de instalar pacotes. Estamos falando do npm init. Seu uso é extremamente básico, apenas digite em seu terminal: npm install <dependência a ser instalada>. Por exemplo: para instalar o pacote express conforme temos no exemplo do package.json acima o seguinte comando seria executado: npm install express. Neste caso o pacote express disponível do repositório da npm será instalado na pasta node_modules/ do projeto na qual o comando foi executado. O módulo também será adicionado às suas dependências no seu package.json

Uma outra função que mencionamos anteriormente a respeito do npm install é sua capacidade de instalar todos os pacotes necessários para um app, ou seja, as dependências listadas na palavra chave dependencies. Para realizar essa ação é só executar o comando da seguinte forma: npm install, sem nenhum outro parâmetro sendo passado.

É possível também especificar a versão do app que deseja instalar. No caso da versão 4.16.3 do express conforme especificada no package.json do exemplo, executaríamos da seguinte forma: npm install express@4.16.3.

No meu fluxo de desenvolvimento sempre usei um pacote do npm chamado nodemon. Ele é muito útil durante o trabalho porque tem a capacidade de perceber qualquer mudança feita em qualquer arquivo de seu projeto e automaticamente reiniciá-lo quando necessário. Então se você está com um bug no código e sua aplicação está crashando ao iniciar, basta alterar o código e salvar o arquivo que sua aplicação será automaticamente reiniciada e você saberá se o problema foi corrigido. Uma mão na roda durante horas e horas de programação. Mencionei essa aplicação porque eu sempre a instalei de forma global em minhas máquinas. Desta forma independente da aplicação que eu estava trabalhando era possível usar o nodemon.

Essa é outra função muito útil do comando install: instalar pacotes de forma global em sua máquina. Uma ressalva sobre aplicações instaladas desta forma é que elas não serão instaladas em seu node_modules/ local da aplicação e sim em uma pasta do seu sistema. Por conseguinte, as permissões de administradores podem ser solicitadas para o processo. Já ia esquecendo de explicar como é feita a instalação de forma global! Apenas execute: npm install <pacote> --global. No caso do nodemon sempre instalei usando: npm install -g nodemon (o -g age como um alias para a global flag).

  1. Para realizar a atualização de pacotes e suas dependências, o comando update pode ser usado. Execute da seguinte forma em seu terminal: npm update <pacote a ser atualizado>.
  2. Em vários projetos ou até frameworks é bem comum o uso do comando start da seguinte forma: npm start. Essa execução nada mais é, por baixo dos panos, a execução de npm run start. E aqui vamos falar de algo que mencionamos brevemente. O controle de fluxo da aplicação através do npm. Dentro da lista de scripts no package.json pode-se definir uma série de comandos a serem executados fazendo uso de npm. Por exemplo:

{
"scripts": {
  "watch": "webpack --watch --progress --colors --config webpack.conf.js",
  "dev": "webpack --progress --colors --config webpack.conf.js",
  "prod": "NODE_ENV=production webpack -p --config webpack.conf.js",
}
}


Dessa forma os seguintes comandos estariam disponíveis:

npm run watch
npm run dev
npm run prod


E eles irão executar os comandos especificados a eles atribuídos. Isso facilita o processo de comandos bem comuns como o test por exemplo. Ou seja, ao invés de você verificar todo o comando de teste necessário ou às vezes até comandos a serem executados antes dele você só baixa o pacote e executa npm run test.

Uma dica para os iniciantes com o NPM: é possível usar alias/apelidos para os comandos. O npm install por exemplo pode ser usado como npm i.

Considerações Finais

E isso é tudo pessoal! Espero que tenham gostado desse guia para iniciantes sobre o NPM. Tratamos aqui da motivação para a criação de gerenciadores de pacotes, sua utilidade e como o Node Package Manager se encaixa em todo esse ecossistema. Adiciono que mesmo para uso do NodeJS e Javascript em geral outros gerenciadores também existem. Pesquise um pouco sobre o yarn e pnpm para ver as diferenças desses outros managers.

Um abraço e até a próxima!

💡
As opiniões e comentários expressos neste artigo são de propriedade exclusiva de seu autor e não representam necessariamente o ponto de vista da Revelo.

A Revelo Content Network acolhe todas as raças, etnias, nacionalidades, credos, gêneros, orientações, pontos de vista e ideologias, desde que promovam diversidade, equidade, inclusão e crescimento na carreira dos profissionais de tecnologia.