Conhecendo mais sobre o NPM
Nas lições mais avançadas desta jornada, é necessário que você tenha um pré-entendimento sobre o funcionamento do gerenciador de pacotes do NodeJS, o NPM
!
Lá na lição que fala sobre Configurações Iniciais, você conheceu um pouco sobre o que é o NPM
, e como ele pode atuar na sua aplicação.
Nesta lição, vamos nos aprofundar um pouco mais no universo do NPM
, de modo a criar projetos com ele, gerenciar pacotes, instalar pacotes, remover pacotes, criar scripts e muito mais!
Vamos nessa? 🤓
O que é o NPM?
O NPM
(Node Package Manager) é o principal gerenciador de pacotes que é usado pela plataforma do NodeJS.
É por meio dele que conseguiremos realizar a instalação de nossos pacotes, atualização dos mesmos, e o gerenciamento de bibliotecas e ferramentas de código de terceiros na sua aplicação.
A grande maioria dos projetos que você for participar, você irá notar que a grande maioria dele faz o uso do NPM
para o gerenciamento de pacotes.
Pensa no NPM
como uma ponte capaz de trazer bibliotecas de terceiros para seu próprio projeto, e também as manter atualizadas, a cada nova funcionalidade que o dono da biblioteca for publicando no seu repositório online.
O NPM
é parecido com o Windows Update da Microsoft, que tem por objetivo, manter todas as atualizações do Windows, além de nos dar a possibilidade de instalar/atualizar/remover novas funcionalidades e recursos, onde tudo isso feito é feito de forma automática.
Além disso, com o NPM
, nós podemos configurar nosso projeto de tal modo que ele consiga rodar scripts por meio do próprio NPM
.
Portanto, com o NPM
você pode:
- Adicionar bibliotecas e ferramentas ao seu projeto por meio de um simples comando (
npm install
). - Manter um arquivo
package.json
que lista todas as dependências do seu projeto, facilitando a instalação de todas as bibliotecas necessárias com um único comando. - Se você desenvolveu uma biblioteca ou ferramenta que deseja compartilhar com a comunidade, poderá publicá-la no repositório
NPM
para que outros possam fazer o seu uso.
Observação: Além do NPM
, temos outros pacotes disponívels no mercado, como é o caso do Yarn
.
É importante ressaltar que raramente um projeto feito com NodeJS, usufrua somente dos core modules disponibilizados pelo próprio ambiente. Por esse motivo, o uso do NPM
se faz totalmente necessário na sua aplicação.
Não existe um core module que valide o seu CPF, por exemplo... mas existem diversos pacotes externos que fazem isso, e talvez você queira utilizá-los na sua aplicação... ou você prefere perder muito tempo reinventado a roda?
Bem, agora que você já sabe a importância do NPM
no seu projeto em NodeJS, vamos parar um pouquinho, e fazer uma pequena reflexão 🤔
Usar pacotes prontos, ou criá-los do zero?
No início da minha carreira como desenvolvedor de software, eu sempre ouvia muito a frase: "não reinvente a roda!", e sabe qual era a minha resposta?
"A RODA PRECISA SER REINVENTADA SIM!".
E até hoje uma parte de mim ainda acredita nisso, pois no final das contas, eu sempre me enxia de orgulho, batia no peito e dizia: "Eu fiz 100% desse sistema, sem precisar instalar nenhuma biblioteca de terceiros!".
E isso era bom, não vou mentir... dava uma sensação de saciamento danado 😅
Porque no final das contas, as pessoas sempre olhavam pra mim e diziam: "Nossa, como você é um gênio...", já outras... "Cara, porque você perdeu tempo com isso?".
É claro que o processo de aprendizado é muito maior quando você decide criar uma biblioteca do absoluto ZERO, ou seja, por meio de funções da própria linguagem e com muuuuita lógica envolvida 🤓
Entretanto, lá no ano de 2015, quando eu tive uma startup acelerada pela Universidade Estácio, chamada de Estácio Nave.
A minha visão começou a mudar um pouco, o que antes eu considerava uma verdade absoluta, aos poucos foi caindo por terra.
A principal delas foi o fato de eu sempre criar minhas próprias bibliotecas do ZERO ABSOLUTO, tipo de coisa que pra mim demandava muito tempo.
E não era apenas as biblioteas, eram os layouts e até mesmo questões de arquitetura 🫣
E se fosse possível, eu criava a minha própria linguagem de programação para ser usada especificiamente naquele projeto (sim, eu tinha umas neuras) 😅
Com o tempo, eu fui percebendo que esse "modus operandis", demandava muito tempo para um tipo de coisa que NÃO INTERESSARIA para meu usuário final.
Ao mesmo tempo que fui percebendo que isso não influênciava em nada no produto final, e que na verdade eu estava era PERDENDO TEMPO 🕖
Uma vez que meus usuários, eles não estavam interessados em saber se a minha aplicação usava PHP
, NodeJS
, NPM
, Yarn
, biblioteca de Fulano de Tal e qualquer outra coisa que não foi criada por mim.
Para o usuário final, o que importava para ele, era se a minha SOLUÇÃO resolvia os problemas DELE! Independentemente do que estava sendo feito por de baixo dos panos.
E outra, você não tem a obrigação de deixar explícito que você fez o uso da biblioteca de fulano de tal, de ciclano, ou de beltrano. Até porque, no final das contas, 98% das pessoas nem saberão que você fez ou faz o uso dessas bibliotecas.
E foi aí que eu comecei a pensar: "Cara, eu to perdendo muito tempo criando uma solução de total autoria, enquanto eu poderia cortar caminho usando pacotes já existentes, e focar no meu objetivo PRIMÁRIO...".
Desde então, meu mindset mudou, e se der pra fazer uso de uma biblioteca de um terceiro, ou de um template pronto, por que não?
Mas daí você pode me perguntar: "E quando começa a fazer sentido eu criar um pacote do ZERO ?".
No meu ponto de vista, só existem duas alternativas que fazem sentido (pra mim) criar pacotes do ZERO:
- Quando você está criando uma solução bem específica, ao mesmo tempo que as soluções e pacotes atuais não te atendem.
- Quando você tem um pé na filantropia, e gosta de ajudar a comunidade de tal modo, que lança suas próprias bibliotecas (código aberto) visando facilitar a vida dos outros desenvolvedores (Exemplo: Pupperter).
É importante que você entenda que a última opção, na maioria das vezes, não te trará retornos financeiros 🫥
Mas... pode fazer com que a sua biblioteca fique famosa a tal ponto, de você receber uma proposta de emprego de uma BIG TECH (Google, Tesla, Facebook, Twitter...), e eu já vi isso acontecer 🤩
Eu por exemplo, há alguns anos atrás lancei um pacote de Streaming de Vídeos para o Laravel, pois naquela época eu não tinha encontrado nenhum pacote que pudesse atender minha aplicação, e como eu também tenho um pé na filantropia, lancei esse pacote para o público em geral 🙂
Até agora não recebi nenhum tostão com ele, muito menos uma proposta de uma Big Tech 😂
Mas o simples fato de algumas pessoas o terem baixado, e como consequência terem solucionado seus problemas (eu acho, porque não tem como saber direito), já é uma coisa que me deixa feliz, ao mesmo tempo, que é um tipo de coisa que dá pra colocar no currículo também, não é verdade?
Se você for parar para pensar, hoje vivemos na Cultura do Remix, onde nada se cria... tudo se remixa. Dificilmente uma nova ideia surge sem qualquer tipo de base fundamentada.
É igual na matemática, que apesar de termos inúmeras fórmulas, elas sempre se resumem nos fundamentos que já são conhecidos, como a adição, diminuição, multiplicação e divisão.
Dito isso, cabe a você (leitor) tirar suas próprias conclusões, se vale a pena ou não criar pacotes do zero, ou fazer o uso de pacotes de terceiros!
Fica aí a reflexão final 😉
Criando um projeto com NPM
Por meio do NPM
, você também pode criar um novo projeto do ZERO, onde este pode conter alguns pacotes e configurações inciais que serão usadas pela sua aplicação.
Para testarmos isso, primeiro você precisa garantir que o pacote NPM
já está instalado na sua máquina.
Para fazer essa verificação, abra o seu terminal (Prompt de Comando) e execute o seguinte código:
npm -v
Se tudo estiver configurado corretamente, o terminal irá retornar a versão atual do NPM
que está instalado na sua máquina:
Observação: Caso seja necessário atualizar a sua versão do NPM
para a mais recente, basta utilizar o seguinte comando no seu terminal:
npm install -g npm
Em seguida, não se esqueça de executar um npm -v
, para checar se está tudo certo.
Como nessa seção nós iremos trabalhar exclusivamente com o NPM
, nada mais justo que criar uma nova pasta no seu computador para agrupar os projetos que iremos criar nesta lição 😉
No meu caso, como estou usando Windows, eu criei uma nova pasta chamada projetosNPM na minha área de trabalho (desktop):
Feito isso, com o seu terminal (Prompt de Comando) aberto dentro da pasta que acabamos de criar (projetosNPM), vamos iniciar um novo projeto por meio do seguinte comando:
npm init
Como você pode ver na ilustração acima, o gerenciador de pacotes gerou uma mensagem de boas vindas, e logo em seguida, pediu para que informássemos o nome do nosso projeto (package name).
De maneira automática, ele induz que o nome do seu pacote (package name) seja o mesmo nome da pasta (em minúsculo).
👉 Aqui você pode pressionar [ENTER], e deixar que o NPM
use o nome da sua pasta como o nome do seu pacote (recomendável).
👉 Ou você pode informar um nome customizado, e pressionar [ENTER]. Lembre-se de usar letras minúsculas e traços em vez de espaços.
A segunda opção, refere-se a versão atual (version) do seu projeto. E como estamos criando-o pela primeira vez, nada mais justo que deixar 1.0.0, ou caso preferir, você pode digitar uma versão customizada. (Por exemplo: 0.0.0 ou 0.0.1)
A description
, refere-se a descrição do seu projeto, o ideal é que você explique em poucas palavras sobre o que o seu projeto se trata.
Já o Entry Point
, refere-se ao ponto de entrada da sua aplicação, que pode ser desde o arquivo index.js
, server.js
, app.js
e entre outros.
Lembra que eu falei que nós podemos executar nossa aplicação em NodeJS diretamente pelo NPM?
Isso geralmente é feito pelo npm start
(spoilers), que por sua vez, por de baixo dos panos, executa o comando node ./app.js
e roda a sua aplicação.
No meu caso, eu deixei meu Entry Point
como index.js
, mas você pode mudar ele mais tarde se quiser 😌 (assim como qualquer outra configuração que fizemos até o momento)
O Test Command
é usado para informar o arquivo principal que irá rodar testes automatizados na sua aplicação.
Como não iremos trabalhar com isso no momento, vamos deixá-lo em branco.
O Git Repository
é o local aonde você insere a URL do repositório que está relacionado com esse projeto.
Se você já tem um repositório Git
criado (por exemplo, no GitHub, GitLab, Bitbucket, etc.), coloque a URL do repositório no campo "git repository"
. A URL pode ser algo como https://github.com/usuario/repositorio.git.
Mas como eu não tenho um repositório no Git dedicado a este projeto, vou deixar em branco, e seguir em frente.
Já as keywords
, nada mais são do que os termos (palavras-chave) que identificam o seu projeto.
Se tivéssemos um projeto de dashboard por exemplo, poderiamos usar os termos: dash
, dashboard
, panel
, admin
, bootstrap
, UX
(você deve separar as palavras-chave por vírgula dentro de keywords).
Como estamos configurando um projeto simples, usei apenas os termos npm
, inicio
.
Como o próprio nome já nos diz, Author
refere-se ao nome da pessoa que criou o projeto. Então nada mais justo que colocar o seu próprio nome (espaços e caracteres especiais são aceitos).
O Licence
(licensa) refere-se a forma com que os outros desenvolvedores poderão usar o seu código, o que define como o código pode ser utilizado, modificado e distribuído. Aqui você pode inserir as seguintes opções:
ISC
: a licença ISC permite que você use, modifique, copie e distribua o código com muitas poucas restrições. É uma das licenças mais permissivas disponíveis que temos no mercado atualmente.
MIT
: permite quase qualquer coisa com o código, incluindo modificar, distribuir e usar em projetos comerciais.
Apache License 2.0
: semelhante à MIT, mas inclui uma cláusula de patente que protege contra ações legais baseadas em patentes.
GNU General Public License (GPL)
: exige que qualquer software derivado também seja distribuído sob a mesma licença, garantindo que as liberdades concedidas pela licença sejam preservadas em projetos derivados.
BSD License
: permite usar, modificar e distribuir o código com poucas restrições.
Creative Commons (CC)
: mais comum em obras criativas, como textos e imagens, do que para software.
No meu caso, deixei como ISC
mesmo...
Por fim, o terminal perguntará se tudo o que você informou está correto, e se sim, digite o termo yes
no terminal e pressione [ENTER].
Observação: qualquer outro comando que você digitar, fará com que você volte a etapa inicial para corrigir suas informações.
Após isso, o assistente de configuração do NPM
será fechado, e dentro da pasta projetosNPM, será criado um novo arquivo chamado de package.json
, que contém as mesmas configurações que acabamos de criar, só que no formato JSON
😆
package.json
:
{
"name": "projetosnpm",
"version": "1.0.0",
"description": "Um projeto de testes feito com NPM",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"npm",
"inicio"
],
"author": "Micilini Roll",
"license": "ISC"
}
Feito isso, vamos entender um pouco mais sobre esse arquivo 🤓
O que é o package.json?
O package.json
é um arquivo gerenciado pelo NPM
, que é fundamental em projetos que fazem o uso da linguagem Javascript ou Typescript.
Ele atua como o coração do seu projeto, gerenciando informações essenciais sobre o projeto e suas dependências.
É por meio dele que o NPM
sabe quais scripts executar, além das bibliotecas que estão instaladas. Pensa nesse arquivo como uma especie de controle de caixa, que lista todos os produtos que você possui na sua loja:
Ou seja, o package.json
é um documento de controle, e sem ele, não temos controle de nada, simples!
O arquivo package.json
possui alguns metados principais:
name
: nome do projeto.
version
: versão atual do projeto.
description
: uma breve descrição do projeto.
author
: informações sobre o autor do projeto.
license
: tipo de licença do projeto (por exemplo, MIT, Apache-2.0).
keywords
: palavras-chave associadas ao projeto que ajudam na descoberta.
browserslist
: configura quais navegadores são suportados pelo projeto, útil para ferramentas como Babel
e Autoprefixer
.
files
: lista arquivos e diretórios a serem incluídos quando o pacote é publicado.
Além disso, a seção scripts
permite definir comandos personalizados que você pode executar com npm run [script-name]
.
Observe alguns exemplos:
"scripts": {
"start": "node index.js",
"test": "jest",
"build": "webpack"
}
Lembra que eu falei que o comando npm start
executa o seu código em NodeJS? Então... olha ele ali executando o node index.js
, por de baixo dos panos 😉
Observando o funcionamento desse arquivo JSON
, acredito que ficou claro como ele funciona, cert?
Note que na estrutura acima, quando o desenvolvedor executar um npm test
, a biblioteca jest
será chamada (ela pode estar associada a um arquivo global de testes).
Da mesma forma que npm build
, vai chamar a biblioteca webpack
para compilar o nosso projeto.
Lembrando que quando digitamos npm
+ [start
, test
, build
], por de baixo dos panos, o NPM
irá procurar pela chave "script"
de modo a achar as sub-chaves "start, test e build".
Dentro do JSON
, podemos ter uma seção dedicada a dependências:
"dependencies": {
"express": "^4.17.1"
},
"devDependencies": {
"jest": "^26.6.3"
}
Que lista todas as bibliotecas necessárias para o funcionamento do projeto em produção. Essas dependências serão instaladas quando você for executar o comando npm install
.
Já o devDependencies
, é mais voltada aos pacotes que são necessários, apenas para o ambiente de desenvolvimento.
Por fim, nós podemos ter também, outras configurações avançadas relacionadas ao nosso projeto:
"main": "index.js",
"engines": {
"node": ">=14.0.0"
},
"repository": {
"type": "git",
"url": "https://github.com/usuario/repositorio.git"
}
main
: o ponto de entrada principal do seu projeto, geralmente um arquivo JavaScript que é executado quando o módulo é requerido.
engines
: especifica quais versões do NodeJS ou outros ambientes são suportados pelo seu projeto.
repository
: informações sobre o repositório do código-fonte (como a URL do Git).
Caso você queira resetar as configurações feitas pelo npm
, basta apagar o arquivo package.json
, e executar o assistente de configuração usando o comando npm init
.
Criando um projeto com NPM de forma enxuta
Caso você queira pular a maioria daquelas configurações do assistente de configuração. Existe uma maneira mais rápida de criar seu projeto com NPM
.
Para isso, basta executar o seguinte comando dentro da pasta raiz do seu projeto:
npm init -y
Por meio da flag -y
, o NPM
irá fazer com que todas as respostas sejam marcadas YES
, o que é equivalente a sairmos pressionando [ENTER] em todas as perguntas 🤣
O ponto bom, é que isso facilita a criação do nosso projeto, visto que podemos alterar o arquivo packge.json
com calma mais tarde 😌
Observação: Você pode utilizar o comando npm init --yes
, que funciona da mesma forma como o npm init -y
.
Instalando seu primeiro pacote
O processo de instalação de um pacote dentro do seu projeto, é a coisa mais simples do mundo, primeiro, certifique-se de que o seu terminal (Prompt de Comando) esteja aberto na pasta raiz do seu projeto (mesma pasta onde contém o arquivo package.json), e em seguida, basta digitar o seguinte comando:
npm install <nome-do-pacote>
Existe uma versão mais enxuta, na qual não precisamos digitar o termo install
, basta usar apenas a letra i
da seguinte forma:
npm i <nome-do-pacote>
Onde está escrito <nome-do-pacote>
, você irá trocar para o nome do pacote que você deseja instalar.
Existe um campo de busca atrelado ao cabeçalho da página. Ali, nós podemos pesquisar por todos os pacotes existentes no banco de dados do NPM
.
Vamos pegar como exemplo, o meu pacote favorito, o Puppeteer:
Na parte direita, você consegue ver um bloco de instalação (install
), que contém o seguinte comando:
npm i puppeteer
Lembrando que o processo de instalação pode demorar um pouco, e isso depende também da sua conexão com a internet.
puppeteer
é o nome do nosso pacote, e executando o comando acima na pasta raiz do seu projeto, fará com que essa biblioteca seja instalada dentro de uma pasta chamada de node_modules.
Ao mesmo tempo que um novo arquivo chamado de package-lock.json
será criado.
A pasta node_modules é onde o NPM
(Node Package Manager) instala todas as dependências do seu projeto, ou seja, é pra lá que vai o código-fonte das bibliotecas de terceiros.
Quando você executa o comando npm install
, o NPM
faz download daqueles pacotes, e os coloca nesta pasta.
Essa pasta é considerada a maior pasta do projeto! Logo, costuma ser a pasta mais pesada!
O package-lock.json
é um arquivo gerado automaticamente quando você executa npm install
. Ele contém um registro detalhado de todas as versões exatas das dependências instaladas no projeto.
Além disso, após a execução do comando npm install
, o arquivo package.json
também sofrerá alterações, você consegue identificar quais foram?
{
"name": "projetosnpm",
"version": "1.0.0",
"description": "Um projeto de testes feito com NPM",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"npm",
"inicio"
],
"author": "Micilini Roll",
"license": "ISC",
"dependencies": {
"puppeteer": "^23.2.0"
}
}
Note que a chave "puppeteer" contendo a versão atual (acima de 23.2.0) foi inclusa neste arquivo. O que indica que o projeto depende do pacote Puppeteer 😉
Vamos ver outros exemplos de pacotes que podemos instalar:
npm i express
npm i cors
npm i cpf
express
: é um framework web que iremos aprender na próxima lição 🤫 (sem spoilers dessa vez, ok?)
cors
: é um pacote que gerencia a política de CORS
do navegador do cliente e servidor.
cpf
: é um pacote completo que é capaz de validar e gerar CPF.
Acessando a documentação de um pacote
O NPM
possui um recurso muito legal chamado de docs
, que pode ser usado para retornar a documentação relacionada ao pacote. Veja como podemos fazer isso:
npm docs <nome-do-pacote>
No comando acima, usamos o docs
para acessar a documentação do pacote.
Geralmente, ele abre uma nova aba no nosso navegador, apontando para a página de documentação daquele pacote (principalmente se for um pacote grande).
Acessando a Home do pacote
Cada pacote do NPM
, pode ter sua própria Home Page (página principal) associado a ele, e geralmente acessamos ela por meio do seguinte comando:
npm home <nome-do-pacote>
Com o comando home
, você pode ser direcionado, ou para a página de documentação relacionada à aquele pacote, ou quem sabe para uma página de apresentação do pacote em sí, onde mostra quais problemas ele se propõe a resolver.
Lembando que isso vai variar de pacote para pacote, existe alguns que só configuram a página de documentação, já outros que trabalham com ambas (e alguns que nem isso tem 😂).
Usando o npm install
Você também pode executar o comando npm install
sem a necessidade de informar o nome do seu pacote, sabia disso?
Quando você executa o comando npm install
sem especificar um nome de pacote, o NPM
instala todas as dependências listadas no arquivo package.json
do seu projeto.
Para vermos o funcionamento disso, vamos excluir a pasta node_modules e o arquivo package-lock.json
, deixando apenas o arquivo package.json
na pasta raiz do projeto:
Como já fizemos a instalação da biblioteca Puppeteer em nosso projeto, o arquivo package.json
ainda vai conter o registro dessa dependência:
"dependencies": {
"puppeteer": "^23.2.0"
}
De modo que, quando executarmos um npm install
, o gerenciador abra esse arquivo (package.json
), identifique as dependencias necessárias, verifique se elas já estão instaladas, e caso não estiverem, ele realiza o download de cada uma delas:
Se você observar, alguns pacotes possuem alguns sinais, como ^
e ~
, mas para que eles servem? 🤨
Sinal ^ (Caret)
O sinal ^
indica que o NPM
pode atualizar a versão da dependência para qualquer versão que não altere o primeiro número não zero à esquerda do ponto decimal.
Sendo assim, ele permite atualizações como: 1.2.x
, 1.x.x
, mas não 2.0.0
ou superior.
Por exemplo, se a dependência estiver especificada como ^1.2.3
, o NPM
instalará a versão mais recente que é 1.x.x
onde o x
pode ser qualquer valor (exemplo: 1.2.4, 1.9.9...), mas não versões 2.0.0
ou superiores.
Isso permite que o projeto receba atualizações de correções e novas funcionalidades que não quebram a compatibilidade, mas mantém a versão principal a mesma.
"dependencies": {
"example-package": "^1.2.3",
}
"Não quebram a compatibilidade" no sentido de versão 1.x.x
manterem a mesma estrutura de métodos e propriedades do código. Pois geralmente as versão 2.x
, 3.x
, 4.x
sempre mudam algo na estrutura.
Sinal ~ (Tilde)
O sinal ~
indica que o NPM
pode atualizar a versão da dependência para qualquer versão que não altere o número menor do ponto decimal.
Sendo assim, ele permite atualizações como: 1.2.x
, mas não 1.3.0
ou superior.
Por exemplo, se a dependência estiver especificada como ~1.2.3
, o NPM
instalará a versão mais recente que é 1.2.x
onde o x
pode ser qualquer valor, mas não versões 1.3.0
ou superiores.
"dependencies": {
"another-package": "~1.2.3"
}
Permitindo atualizações sem restrições
Se você deseja que o NPM
instale sempre a versão mais recente de uma dependência dentro de uma faixa principal específica, como qualquer versão 2.x.x
ou 3.x.x
, você pode usar a versão "sem restrições" ou configurar o versionamento no package.json
para refletir isso.
Vejamos alguns exemplos:
"dependencies": {
"puppeteer": "23.2.0"
}
No caso do exemplo acima, como não especificamos nenhuma restrição, o NPM
vai buscar sempre a versão que foi especificada na época, que é a 23.2.0
.
"dependencies": {
"puppeteer": ">=23.2.0"
}
O símbolo de maior ou igual (>=
), permite que seja instalado a partir da versão 23.2.0
ou superior, e isso inclui 24.x
, 25.x
e por ai vai.
Mas cuidado ao fazer isso, pois qualquer atualização de pacote, poderá causar incompatibilidade com seu código.
"dependencies": {
"example-package": ">=2.0.0 <4.0.0"
}
">=2.0.0 <4.0.0"
permitirá qualquer versão a partir de 2.0.0
até, mas não incluindo, 4.0.0
seja aceita. Isso garante que você receba qualquer versão dentro da faixa 2.x.x
e 3.x.x
.
Lembrando que você pode usar o <=
alí também, o que permite a versões menores ou iguais a 4.x.x
mais não superiores a ela.
Instalando versões específicas com NPM
Você também pode escolher a versão do pacote que você deseja instalar no seu projeto, e isso pode ser feito de duas formas diferentes:
npm install <nome-do-pacote>@1.0.0
npm install <nome-do-pacote>@latest
O primeiro comando (@1.0.0
) procura e instala a versão 1.0.0
, já o segundo comando (@latest
) busca pela versão mais nova disponível.
Importando um pacote para dentro do seu projeto em NodeJS
Após a instalação dos seus pacotes na pasta do seu projeto, basta que você use o require
dentro do seu index.js
da seguinte forma:
const pacote = require('nome-do-pacote');
Lembrando que cada pacote possui uma documentação diferente, logo, cada pacote possui métodos e propriedades diferentes 😉
Chencando atualizações de pacotes
Para verificar os pacotes que necessitam de uma atualização, podemos usar o seguinte comando:
npx npm-check-updates -u
O npx
é um utilitário incluído com o NPM
que permite executar pacotes NodeJS diretamente sem precisar instalá-los globalmente. Ele procura o pacote no repositório do NPM
, o baixa (se necessário) e o executa.
O npm-check-updates
, é um comando do NPM
que busca e lista todas as atualizações de pacotes que já existem dentro do package.json
.
Por fim, temos a tag -u
, que instrui o npm-check-updates
a atualizar o arquivo package.json
com as versões mais recentes das dependências, substituindo as versões atuais por essas versões mais novas.
Atualizando todos os pacotes
Com o NPM
, você pode atualizar todos os pacotes instalados. Para isso, com o terminal (Prompt de Comando) aberto dentro da pasta raiz do seu projeto, execute o comando:
npm update
Ele verifica o package.json
e o package-lock.json
, de modo a atualizar os pacotes instalados para as versões mais recentes que respeitam as faixas de versão especificadas (>
, <
, ^
, ~
, =
).
Observação: Você também pode usar o comando npm install
para atualizar todos os pacotes.
Atualizando um pacote específico
Para atualizar um pacote específico, você pode usar o seguinte comando:
npm update <nome-do-pacote>
Esse comando atualiza apenas o pacote especificado para a versão mais recente permitida pelas restrições (>
, <
, ^
, ~
, =
) de versão no package.json
.
Atualizando um pacote para a última versão disponível
Se você deseja atualizar um pacote para a versão mais recente disponível, independentemente das restrições
(>
, <
, ^
, ~
, =
) de versão especificadas no package.json
, você pode usar o seguinte comando:
npm install <nome-do-pacote>@latest
O @latest
força a instalação da versão mais recente do pacote, e atualizará o package.json
e package-lock.json
para refletir essa versão.
Checando os pacotes que precisam ser atualizados
O NPM
possui um comando chamado de outdated
, que visa listar todos os pacotes instalados na pasta do seu projeto, e que precisam de uma atualização:
npm outdated
Note que no caso da ilustração acima, foi identificado que um pacote possui uma versão mais recente.
Observação: Com o comando npm update
, você pode atualizar não só esse pacote, mas como todos os outros que também precisam ser atualizados.
Removendo um pacote
Para remover um pacote que está listado em seu package.json
e na pasta node_modules, você pode usar o comando
npm uninstall <nome-do-pacote>
Com o uninstall
, o NPM
removerá o seu pacote tanto da pasta node_modules, quantos dos arquivo package.json
e package-lock.json
.
Removendo todos os pacotes
Para remover todos os pacotes, o processo segue de forma manual 🥲
1° Passo) Remova a pasta node_modules e package-lock.json
.
2° Passo) Dentro do package.json
remova as chaves das dependências da seguinte forma:
{
"name": "seu-projeto",
"version": "1.0.0",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
}
// Remova as seções dependencies e devDependencies
}
E não se esqueça de limpar o cache do NPM
depois de uma limpeza, ou atualização:
npm cache clean --force
Usando o npm install em conjunto com as flags
Quando você usa o comando npm install <pacote>
, há várias flags que você pode utilizar para controlar o comportamento da instalação.
Veremos nos próximos tópicos, cada uma delas 😌
-g ou --global
Instala o pacote globalmente em vez de localmente. Pacotes instalados globalmente ficam disponíveis em qualquer lugar no sistema.
npm install -g typescript
Lembrando que você pode executar um require
normalmente como se o pacote estivesse instalado na pasta node_modules, essa estratégia vai funcionar, pois o NodeJS é inteligente o suficiente para não só buscar na pasta do projeto, como buscar de forma global, isto é, caso o pacote tenha sido instalado de forma global.
Para remover um módulo que você instalou globalmente, basta utilizar o seguinte comando:
npm remove <nome-do-pacote> -g
Não se esqueça de informar os comandos remove
e -g
, para que o NPM
saiba que o pacote que você quer remover está instalado de forma global 😉
--save
Adiciona o pacote à seção dependencies do package.json.
É importante ressaltar que essa flag é implícita nas versões mais recentes do NPM
, e não precisa mais ser usada explicitamente.
npm install <nome-do-pacote> --save
Isso significa dizer que, quando utilizamos o comando npm install <nome-do-pacote>
, por de baixo dos panos, o NPM
já está salvando esse pacote, ou seja, ele já usa a flag --save
.
--save-dev
Adiciona o pacote à seção devDependencies
do package.json
.
Há uma possibilidade de instalar pacotes que só irão ser executados apenas no ambiente de desenvolvimento, e para isso usamos a flag --save-dev
:
npm install <nome-do-pacote> --save-dev
Dentro do package.json
, ele fica em uma seção totalmente separado dos demais.
Isso ajuda durante a build de produção, pois nesse caso específico, o NPM
não vai baixar esses pacotes no servidor online (servidor de produção).
Um grande exemplo disso, são alguns testes unitários que não precisam estar no servidor de produção, e também o caso do Nodemon, em que usamos o PM2 para isso.
--save-peer
Adiciona o pacote à seção peerDependencies
do package.json
.
npm install <nome-do-pacote> --save-peer
--save-optional
Adiciona o pacote à seção optionalDependencies
do package.json
.
npm install <nome-do-pacote> --save-optional
--no-save
Instala o pacote sem atualizar o package.json
ou o package-lock.json
.
npm install <nome-do-pacote> --no-save
O comando --no-save
no contexto do NPM
é usado para instalar pacotes sem salvar a referência no arquivo package.json
.
Isso significa que o pacote será instalado apenas na pasta node_modules do seu projeto, e não será adicionado às dependências do seu projeto no package.json
.
Sendo assim, se algum dia você compartilhar o package.json com alguém,
--legacy-peer-deps
Ignora as peerDependencies
e instala o pacote mesmo se houver conflitos de versão, o que se torna bem útil quando há problemas com dependências peer
conflitantes.
npm install <nome-do-pacote> --legacy-peer-deps
--strict-peer-deps
Garante que a instalação falhe se houver conflitos de peerDependencies
, forçando uma resolução mais rigorosa.
npm install <nome-do-pacote> --strict-peer-deps
--no-optional
Não instala as dependências marcadas como optionalDependencies
no package.json
.
npm install --no-optional
--production
Instala apenas as dependências listadas em dependencies, ignorando devDependencies
e optionalDependencies
. Útil para ambientes de produção.
npm install --production
--dry-run
Simula a instalação sem realmente modificar o sistema de arquivos. Útil para ver o que seria instalado antes de executar a instalação real.
npm install <nome-do-pacote> --dry-run
--verbose
Fornece informações mais detalhadas durante a instalação. Útil para depuração.
npm install <nome-do-pacote> --verbose
--prefix
Instala pacotes em um diretório específico em vez do diretório atual. É útil para configurar projetos em locais não padrão.
npm install <nome-do-pacote> --prefix /path/to/directory
--no-audit
Desativa a auditoria de segurança que normalmente é realizada após a instalação.
npm install <nome-do-pacote> --no-audit
--audit-level
Define o nível de severidade para a auditoria de segurança. Pode ser low
, moderate
, high
ou critical
.
npm install <nome-do-pacote> --audit-level=high
--cache
Define um diretório de cache personalizado para o npm usar durante a instalação.
npm install <nome-do-pacote> --cache /path/to/cache
Usando flags de forma combinada
Você pode combinar várias dessas flags para ajustar o comportamento da instalação.
Por exemplo, vamos supor que você queira instalar um pacote globalmente, sem atualizar o package.json
, você poderia usar o comando:
npm install -g <nome-do-pacote> --no-save
Criando seus próprios scripts por meio do NPM
Talvez você deve ter imaginado, quando aprendeu o funcionamento da chave "scripts"
do package.json
, a seguinte situação: Será que é possível adicionar meus próprios scripts personalizados?
E a resposta é SIM, você PODE! 🤩
Graças a chave "scripts"
do arquivo package.json
, você pode executar uma série de comandos, digitando apenas um ÚNICO comando.
Para exemplificar isso, vamos supor que você deseja executar o comando node ./index.js
informando apenas start
no terminal, você pode fazer isso da seguinte forma:
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node ./index.js"
},
Note que eu adicionei uma nova chave chamada start
dentro de scripts, que possui um comando em NodeJS.
No terminal, basta executar o comando: npm start
, que por de baixo dos panos, é como se tivéssemos executado o node ./index.js
.
Qual a linguagem usada dentro de scripts do NPM?
A linguagem utilizada é essencialmente a shell scripting
(ou script de shell), e isso significa que você pode escrever comandos que são executados pelo shell
do seu sistema operacional.
Como é o caso do Bash
no Linux e macOS, ou quem sabe o Command Prompt/Powershell
no Windows, tudo vai depender do sistema operacional que o seu projeto estiver rodando.
Observação: Existem algumas chaves dentro de "scripts"
que só são executadas em conjunto com o run
, como por exemplo:
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node ./index.js"
"micilini": "...."
},
...
npm start //Funciona!
npm run start //Funciona!
npm micilini // Não funciona!
npm run micilini //Funciona!
Vale lembrar que o comando npm start
é uma exceção especial no NPM
. (assim como o npm test).
Quando você define um script com a chave "start"
no seu package.json
, o NPM
permite que você execute esse script simplesmente com npm start
sem precisar usar o npm run start
explicitamente (apesar de que o uso do comando npm run start, também funciona).
E como a chave "micilini"
não faz parte de nenhuma exceção, nos vemos obrigados a executar o comando: npm run micilini
. (Se você tivesse uma outra chave chamada "roll", você ainda precisaria usar o npm run roll...)
Além disso, você pode retornar no seu terminal todos os scripts suportados pelo seu projeto, para isso basta executar o comando abaixo:
npm run
Pacotes Executáveis (npx)
Alguns pacotes nem sempre vão precisar do uso do comando require
dentro do seu arquivo Javascript, uma vez que se tratam de scripts executáveis, e que resultam em alguma ação do nosso computador.
Um grande exemplo disso, são os pacotes: Nodemon, React, ESLint, Mocha, Prettier e entre outros... Onde alguns deles podem ser executados de forma global usando apenas a linha de comando (prompt).
Vamos pegar como exemplo, o pacote do React que é executado pelo comando npx
:
npx create-react-app <nome-do-projeto>
Se você acompanhou a Jornada ReactJS aqui no Portal da Micilini, sabe que o comando acima, cria um novo projeto com ReactJS contendo toda a estrutura de arquivo.
Portanto, no caso do npx create-react-app
, temos uma série de processos que são simplificados, incluindo a própria criação dos arquivos package.json
.
Apesar disso, os projetos feitos em React ainda precisam ser executados com npm start
.
NPM vs NPX
O NPM
(Node Package Manager) é o gerenciador de pacotes padrão para NodeJS, cujo o principal objetivo é instalar, atualizar, remover e gerenciar pacotes do NodeJS e suas dependências.
Já o NPX
(Node Package Execute) é uma ferramenta que vem com o NPM
, e é usada para executar pacotes NodeJS que não estão necessariamente instalados no projeto ou no sistema.
Se tornando útil para executar ferramentas e utilitários sem a necessidade de instalá-los globalmente ou como dependências do projeto.
No caso do NPM
, podemos dizer que:
- Foca na instalação e gerenciamento de pacotes, seja localmente ou globalmente.
- Instala pacotes que são adicionados ao
package.json
ou ao sistema. - Permite controlar as versões de pacotes no
package.json
e usa as versões especificadas para instalações.
No caso do NPX
:
- Foca na execução de pacotes e scripts sem a necessidade de instalação permanente.
- Executa pacotes diretamente sem adicioná-los ao
package.json
ou instalar globalmente. - Executa a versão mais recente do pacote disponível, a menos que uma versão específica seja fornecida.
Resumindo, o NPM
é usado para gerenciar pacotes que são utilizados diretamente no projeto (require
), ou seja, dentro dos arquivos Javascript. Já o NPX
é usado para instalar pacotes que não estão ligados diretamente ao projeto em sí, mas que apoiam o mesmo!
Alterando configurações do NPM
Podemos utilizar o comando npm config set
, para configurar certas opções, de modo a definir valores específicos para a configuração do nosso gerenciador.
Isso vai permitir que o comportamento do NPM
possa ser ajustado de acordo com as nossas necessidades, e preferências individuais.
E não, o comando que iremos aprender agora, não tem nada haver com o package.json
, mas sim as configurações do próprio NPM
que esta instalado na sua máquina, ok?
A sintaxe básica da útilização do NPM
é esta:
npm config set <key> <value>
<key>
: é a chave de configuração que você deseja definir.
<value>
: é o valor que você deseja atribuir à chave de configuração.
Vamos ver alguns exemplos da sua utilização abaixo 😉
Alterando as preferências de usuário
Você pode usar o comando init-author-name
, para deixar pré-configurado o nome do autor do projeto, sempre que você for usar o comando npm init
.
npm config set init-author-name "Seu Nome"
Isso fará com que da próxima vez que você execute um novo projeto usando npm init
, o nome do autor já venha preenchido com o nome que você escolheu.
Você pode recuperar o nome escolhido usando o comando get
da seguinte forma:
npm config get init-author-name
O comando acima irá retornar o nome do autor que está setado de forma padrão no NPM
.
Para retornar todas as configurações de uma só vez, utilize o comando:
npm get
Para remover o valor padrão, basta utilizar o comando delete
da seguinte forma:
npm config delete init-author-name
Lembrando que a mesma coisa pode ser feita com os comandos de configuração que iremos aprender abaixo:
init-author-name
: nome do autor padrão a ser usado em novos pacotes.
npm config set init-author-name "Seu Nome"
init-author-email
: email do autor padrão a ser usado em novos pacotes.
npm config set init-author-email "seuemail@example.com"
init-author-url
: URL do autor padrão a ser usada em novos pacotes.
npm config set init-author-url "https://seusite.com"
init-license
: licença padrão a ser usada em novos pacotes. Por exemplo, MIT
.
npm config set init-license "MIT"
init-version
: versão padrão inicial do pacote. Geralmente, 1.0.0
.
npm config set init-version "1.0.0"
init-description
: descrição padrão a ser usada em novos pacotes.
npm config set init-description "Descrição padrão do pacote"
init-main
: arquivo principal padrão para o pacote. Por exemplo, index.js
.
npm config set init-main "index.js"
init-scripts
: scripts padrão para o pacote. Esses podem incluir test
, start
, etc.
npm config set init-scripts '{"test": "echo \"Error: no test specified\" && exit 1"}'
init-keywords
: palavras-chave padrão para o pacote.
npm config set init-keywords "keyword1, keyword2"
Lembrando que:
- Usamos o comando
set
para setar um valor (npm config set <key> <value>
) - Usamos o comando
get
para recuperar e consultar um valor (npm config get <key>
) - Usamos o comando
delete
para remover o valor padrão (npm config delete <key>
)
Para consultar a documentação completa com todas as configurações do NPM
, acesse este link.
Listando os pacotes instalados
Por meio do terminal (Prompt de Comando), é possível analisarmos cada pacote que está instalado na pasta do nosso projeto, isso tanto globalmente, quanto os pacotes que estão instalados no projeto.
Para fazer este tipo de verificação, dentro da pasta do seu projeto, você pode verificar os pacotes instalados por meio do seguinte comando:
npm list
O list
irá listar todos os pacotes que estão instalados na pasta do seu projeto:
Você pode esconder algumas partes da sua arvore de pacotes usando a flag --depth=0
:
npm list --depth=0
Sendo que o 0
pode ser alterado para 1
, 2
, 3
e etc... quanto maior for o número, maior será a arvore de pacotes dependentes que será mostrado no prompt.
Agora, para listarmos as dependências que estão instaladas globalmente, basta usar a flag -g
da seguinte forma:
npm list -g
Lembrando que você pode usar a flag --depth
em conjunto com a -g
😋
Limpando dependências não utilizadas no seu projeto
Exitirão momentos em que você vai desejar fazer uma limpeza nas dependências do seu projeto.
Pensando nisso, a equipe do NPM
desenvolveu uma nova funcionalidade capaz de remover todos os pacotes que não estão sendo utilizados no seu projeto de forma automática.
Para isso, a primeira coisa que você precisa fazer é: Abrir o package.json
, e ir removendo manualmente, os pacotes que você não precisa mais:
Em seguida, basta abrir o terminal (Prompt de Comando) na pasta raiz do seu projeto e executar:
npm prune
O prune
vai abrir o seu package.json
, recuperar todos os pacotes alí presentes, e vai comprar com os pacotes existentes dentro da pasta node_modules. Afim de remover todos os pacotes que não estão listados no seu arquivo JSON
.
Ele abstrai o fato de termos que remover manualmente a pasta de cada pacote existente dentro de node_modules, o que faz com que a gente ganhe um pouco de tempo no desenvolvimento.
Realizando uma busca de pacotes no NPM diretamente pelo terminal
O gerenciador NPM
é tão completo, que ele abstrai o fato de precisarmos entrar na página principal deles para buscar por um determinado pacote 😯
Usando o terminal (Prompt de Comando), você é capaz de realizar uma busca pelos pacotes existentes no NPM
, para isso basta usar o comando search
da seguinte forma:
npm search <nome-do-pacote>
No comando acima, nos foi retornado todos os pacotes que levam a keyword cpf
. (alí usamos o comando npm searc cpf)
Veja quantos pacotes que trabalham com CPF, e que podemos usar no nosso projeto, muitos, não? 🤩
Você pode fazer o uso das aspas duplas para que o NPM
entenda que você está buscando por um pacote só (em vez de dois):
npm search "react test"
Analisando e limpando o cache do NPM
O NPM
possui um comando chamado de npm cache verify
, que é útil para examinar o cache do próprio NPM
, de modo a verificar se o mesmo está íntegro e não corrompido.
npm cache verify
E sim, durante a movimentação dos arquivos do seu projeto, muita coisa pode ser corrompida, ou até mesmo perdida 😱
Este comando, gera um relatório sobre o estado do cache, incluindo informações sobre o tamanho do cache, e quaisquer problemas encontrados, como arquivos corrompidos ou inconsistentes.
Se encontrar problemas, o comando npm cache verify
pode corrigir automaticamente alguns deles, removendo arquivos corrompidos e liberando espaço.
Para termos a certeza que o cache foi apagado, você pode utilizar o comando:
npm cache clean --force
A flag --force
vai forçar uma limpeza de cache por parte do NPM
, use com cautela!
Identificando vulnerabilidades nos pacotes do nosso projeto
Durante a sua jornada como desenvolvedor, durante alguns momentos, você irá se deparar com as seguintes mensagens de alerta:
Alegando que foram encontradas uma ou mais vulnerabilidades nos pacotes de terceiros 😱
E a primeira pergunta que sempre vem a mente é: Será que eu devo me preocupar?
Antes de responder a essa pergunta, você precisa entender que nem todo criador de um pacote, possui todos os conhecimentos necessários para deixá-lo seguro.
E além disso, 95% dos pacotes possuem algum tipo de vulnerabilidade, comumente classificada como baixa (low) ou mediana (medium).
Isso significa dizer que é muuuuuito raro termos um projeto sem nenhum tipo de vulnerabilidade. As vezes, o NPM
classifica um pacote como vulneravél, sendo que ele não é tão vulnerável assim.
Com relação as vulnerabilidades do tipo baixa ou media, você não precisa se preocupar muito. Agora vulnerabilidades do tipo Alta (High) já merecem seu ponto de atenção!
Além disso, é importante que você saiba, que nem sempre o criador do pacote vai ter tempo para corrigir essa vulnerabilidade, o que implica na mudança do próprio pacote em sí, ou seja, deixar de usá-lo para usar um outro mais seguro 😉
Agora, iremos aprender um comando específico do NPM
capaz de detectar falhas de segurança em cada um dos nossos pacotes:
npm audit
Com este comando, o NPM
nos retornará um relatorio bem detalhado das possíveis falhas de segurança existente em cada um dos nossos pacotes.
Observação: É super importante que você (desenvolvedor), fique checando de tempo em tempos, possíveis problemas de vulnerabilidade relacionado com os pacotes de terceiros.
Para corrigir as vulnerabilidades, basta usar o comando fix
em conjunto com o comando npm audit
:
npm audit fix
O comando fix
, ajusta tudo o que for necessário para corrigir os problemas de vulnerabilidade nos pacotes de terceiros.
Mas lembre-se que nem sempre ele consegue corrigir, ok? Isso se deve ao fato de algumas restrições do próprio NPM
e também a falta de versões recentes dos pacotes de terceiros.
Existem algumas correções de vulnerabilidades, em que o NPM
não consegue realizar a correção, pois existem grandes chances de quebrar o seu projeto.
Em casos assim, como uma última alternativa, você pode usar a flag --force
, para forçar uma correção:
npm audit fix --force
NPM View
O gerenciador de pacotes (NPM), possui uma funcionalidade muito interessante chamada de view
.
Seu objetivo é colher o máximo de informações relacionadas a um determinado pacote (esteja ele instalado na nossa máquina local, ou não).
Para utilizá-lo é bem simples, basta digitar o comando abaixo no terminal:
npm view
Note que temos diversas informações, desde as versões de distribuição, mantenedores, versões legadas, últimas, alpha, beta e entre outras.
Para instalar uma determinada versão, você pode utilizar os comandos abaixo, logo após o nome do pacote (como já vimos antes):
@latest
@alpha
@csp
@v2-latest
@legacy
- E entre outras....
Por exemplo:
npm install <nome-do-pacote>@latest
npm install <nome-do-pacote>@alpha
npm install <nome-do-pacote>@csp
npm install <nome-do-pacote>@v2-latest
npm install <nome-do-pacote>@legacy
Reduzindo pacotes duplicados
Algumas bibliotecas podem depender de uma mesma biblioteca em comum. O que ocasiona uma duplicação de bibliotecas na pasta do seu projeto.
Por exemplo, o pacote A depende do pacote C versão 1.0.0, e o pacote B também depende do pacote C, só que a versão 1.3.7.
Concorda comigo que o pacote C está duplicado dentro do nosso projeto?
E apesar de ambos os pacotes estarem fazendo o uso de versões diferentes, ainda assim, o pacote C está duplicado?
Sim, se você se aventurar nas pastas do node_modules, verá que existirão duas versões do pacote C 😅
Pensando em resolver essa questão, a equipe de desenvolvimento do NPM
lançou uma funcionalidade chamada de dedupe
(você também pode usar apenas ddp) que pode ser usada de ambas as formas:
npm dedupe
npm ddp
Com ele, nós podemos realizar uma pesquisa na árvore de pacotes local, na tentativa de simplificar a estrutura geral, movendo as dependências para cima na árvore, onde elas possam ser compartilhadas de forma mais eficaz por vários pacotes dependentes.
No final, o resultado ficaria igual a ilustração abaixo:
Ou seja, o comando npm dedupe
, pega a versão mais recente do pacote duplicado, extrai ele para uma pasta superior, e faz referência a ele nos pacotes que os utiliza.
Observação: o npm dedupe
, não reduz pacotes com versão muito diferentes, por exemplo: 1.3.7
e 2.0.5
, pois ele entende que dá versão 1x
para 2x
, muita coisa pode ser alterada, e que uma possível mudança afetaria o bom funcionamento do seu projeto.
Conclusão
Nossaaa, que conteúdo denso, heim? 🥸
Nesta lição você aprendeu bastante coisas relacionadas ao gerenciador NPM
🥳
Vimos desde os conceitos básicos, até comandos mais avançados que não são muito utilizados no dia a dia.
Fique a vontade para consultar essa lição sempre que desejar, e até a próxima 🤩