Gerenciar atualizações de dependência no projeto do Node.js

Concluído

Como desenvolvedor da Tailwind Traders, é importante manter nossos pacotes atualizados. Isso ajuda a garantir que estejamos usando os recursos e correções mais recentes. Ele também nos ajuda a evitar vulnerabilidades de segurança. Nesta unidade, você aprenderá a gerenciar dependências em um projeto do Node.js. Você aprenderá a atualizar pacotes, usar controle de versão semântico e gerenciar problemas de segurança.

Considerações antes de atualizar um pacote

Antes de atualizar um pacote, considere:

  • Tipo de atualização: Entenda se é uma correção secundária, um novo recurso ou uma alteração importante que pode interromper o seu código. O controle de versão semântico pode ajudar a identificar isso.
  • Configuração do projeto: Certifique-se de que o projeto esteja definido para receber apenas as atualizações desejadas para evitar alterações inesperadas.
  • Segurança: Lembre-se de possíveis vulnerabilidades. Use o recurso de auditoria do npm para identificar e atualizar pacotes problemáticos.
  • Teste: Certifique-se de que os testes sejam aprovados após a atualização. Se você não tiver testes, considere adicioná-los. Seu aplicativo pode se comportar de forma diferente após uma atualização, e os testes validam o comportamento correto.

Controle de versão semântico para definir o comportamento de atualização

O controle de versão semântico é um padrão fundamental no desenvolvimento de software. Ele é essencial para publicar e usar pacotes npm. Ele ajuda a gerenciar riscos de atualização indicando o tipo de alterações em uma nova versão. Um número de versão tem seções específicas para refletir essas alterações:

Tipo de versão Position Sintaxe O que acontece Abordagem de atualização
Grave x.0.0 ou * Alterações de 1.0.0 para 2.0.0 indicam alterações significativas. Ajustes de código podem ser necessários. Confortável com atualizações imediatas para a versão principal mais recente, reconhecendo possíveis alterações de código.
Secundária 1.x.1 ou ^ As alterações de 1.2.9 para 3.0 apresentam novos recursos. O código existente ainda deve funcionar. As atualizações normalmente são seguras. Aberto a novos recursos, mas sem alterações significativas.
Patch Firewall 1.1.x ou ~ As alterações de 1.0.7 para 1.0.8 significam correções de bugs. As atualizações devem ser seguras. Aceitação de correções de bug.

Para projetos pequenos do Node.js, você pode atualizar livremente para as versões mais recentes. Mas, para projetos maiores, as atualizações precisam de um pensamento cuidadoso e nem sempre são automáticas. Em geral, atualizar dependências menores, com menos dependências próprias, facilita o processo.

Antes de atualizar uma ou mais dependências, você deve configurar o arquivo package.json para obter um comportamento previsível ao executar o comando npm update <name of dependency>. O Node.js usa um conjunto de símbolos que permite definir como deseja que seus pacotes sejam atualizados.

Atualizar um pacote com a CLI do npm

Você pode instalar um pacote usando o comando install ou update no npm. Esses comandos agora são em grande parte intercambiáveis. Para atualizar um pacote, você normalmente usa:

  • Versão mais recente: npm update <package name>@latest.
  • Versão específica: npm update <package name>@<optional version number>.

O processo de atualização depende de dois fatores:

  • Argumento de versão: Se um número de versão for especificado no comando npm update, o npm buscará e instalará essa versão específica.
  • Entrada do arquivo de manifesto: O arquivo package.json contém regras para atualizar dependências. Por exemplo, "dependencyName": "1.1.x" significa que o npm buscará a versão que corresponde a esse padrão.

Entender o controle de versão

Três arquivos controlam o controle de versão de dependências:

  • package.json: Este arquivo define a versão do pacote que você deseja usar. É o arquivo de manifesto do seu projeto. Ele contém os metadados para seu projeto, incluindo as dependências.
  • package-lock.json: Este arquivo descreve a árvore exata que foi gerada, de modo que as instalações subsequentes são capazes de gerar árvores idênticas, independentemente das atualizações de dependência intermediária. Este arquivo destina-se a ser confirmado em repositórios de origem.
  • shrinkwrap.json: Este arquivo é criado pelo npm shrinkwrap comando CLI e é semelhante ao package-lock.json. A principal diferença entre os comandos é que as versões de pacote especificadas em npm-shrinkwrap.json não podem ser substituídas pelos usuários. Além disso, o arquivo é compatível com versões mais antigas do npm (versões 2-4), enquanto npm-shrinkwrap.json é compatível com o package-lock.json npm versão 5 e posterior. Portanto, você pode encontrar npm-shrinkwrap.json ao manter bases de código herdadas. A maioria dos desenvolvedores usará package-lock.json em vez de npm-shrinkwrap.json. Uma exceção em que npm-shrinkwrap.json é preferencial é para instalações globais de daemons e ferramentas de linha de comando em que os desenvolvedores desejam garantir que as versões exatas dos pacotes especificados sejam instaladas.

Exemplo de determinação da versão do pacote

Considere um cenário em que você está usando a versão 1.2 em seu código e, em seguida, a versão 1.4 é lançada, interrompendo seu código. Se alguém instalar seu aplicativo neste momento, ele receberá um aplicativo não funcional. Mas, se houver um arquivo package-lock.json especificando a versão 1.2, essa versão será instalada.

Veja um exemplo de como determinar qual versão de um pacote está instalada:

  • Se os arquivos package.json e package-lock.json concordarem em uma regra de versão, não haverá conflito. Por exemplo, se package.json especificar 1.x e package-lock.json especificar a versão 1.4, a versão 1.4 será instalada.
  • Se package.json especificar uma versão mais específica como 1.8.x, ela substituirá o arquivo package-lock.json, que declara a versão mais antiga de 1.4. Nesse caso, a versão 1.8.0 ou uma versão posterior do patch será instalada, se disponível.

Localizar e atualizar pacotes desatualizados com o npm desatualizado

O comando npm outdated é usado para identificar pacotes que têm versões mais recentes disponíveis. Quando executado, ele fornece uma lista destes pacotes desatualizados:

Package       Current    Wanted   Latest     Location     Depended by
lodash        1.0.0      1.0.0    4.17.19    lock-test    main-code-file
node-fetch    1.2.0      1.2.0    2.6.0      lock-test    function-code-file

As colunas na saída incluem:

Coluna Descrição
Pacote O pacote desatualizado.
Atual A versão atual instalada do pacote.
Procurado A versão mais recente que corresponde ao padrão semântico especificado no arquivo package.json.
Mais recente A última versão do pacote.
Location O local da dependência do pacote. O comando outdated rastreia todos os pacotes instalados nas várias pastas node_modules.
Dependência O pacote que tem a dependência.

Gerenciar problemas de segurança com a auditoria do npm

Sempre que você instala ou atualiza um pacote, você obtém uma resposta de log que informa qual versão foi instalada e se há vulnerabilidades. O log lista vulnerabilidades. Se você tiver vulnerabilidades críticas ou altas, deverá atualizar o pacote.

Um exemplo de resposta de log é:

+ lodash@1.3.1
added 1 package from 4 contributors and audited 1 package in 0.949s
found 3 vulnerabilities (1 low, 2 high)
  run `npm audit fix` to fix them, or `npm audit` for details

Para corrigir um problema e aplicar uma atualização, você pode executar o comando npm audit. Esse comando lista cada vulnerabilidade.

O comando npm audit fix tenta resolver vulnerabilidades atualizando para uma versão secundária em que o problema não existe. No entanto, isso poderá não estar disponível se a correção estiver realmente na próxima versão principal.

Nesses casos, talvez seja necessário usar npm audit fix --force, o que pode introduzir alterações significativas atualizando para a versão principal. Executar este comando é uma decisão que você deve tomar com cuidado. Você deve estar ciente das alterações interruptivas e usar npm update para atualizar seu código, incluindo vulnerabilidades.

Uma vulnerabilidade é uma falha de código que pode ser explorada por invasores para executar ações mal-intencionadas, potencialmente comprometendo seus dados e sistemas. É muito importante resolver essas vulnerabilidades imediatamente.

Dada a descoberta frequente de vulnerabilidades, o GitHub tem um recurso que verifica repositórios e cria automaticamente PRs sugerindo atualizações para versões mais seguras. Executar npm audit regularmente é uma boa prática para identificar e corrigir vulnerabilidades, contribuindo para a segurança geral do seu projeto.

O fluxo de trabalho recomendado para atualizações é:

  1. npm run test: Verifique se os testes existentes são aprovados antes de iniciar este processo de atualização.
  2. npm audit: para verificar se há vulnerabilidades na versão atual que você está usando. As informações de npm audit podem recomendar a atualização para uma versão principal. Você deve examinar cuidadosamente as alterações interruptivas se houver alguma listada.
  3. npm outdated: para listar todos os pacotes desatualizados. Esse comando fornece informações nas colunas Wanted, Latest e Location.
  4. Atualizar com npm update:
    • Para projetos menores (algumas dependências no package.json: você pode tentar npm update para atualizar todas as dependências e executar seus testes.
    • Para projetos maiores (com muitas dependências no package.json: atualize um único pacote ou família de pacotes (como Next.js e React) e execute os testes.
  5. npm audit: verifique se não há vulnerabilidades críticas ou altas. Se as vulnerabilidades ainda existirem, use npm update com o nome do pacote e a versão principal recomendada em npm audit.
  6. npm run test novamente.
  7. Faça check-in do seu package.json e package-lock.json.