Manual do Node.js., Parte 4: Arquivos npm, package.json e package-lock.json

Hoje estamos publicando a quarta parte da tradução do Node.js. Neste artigo, começaremos a falar sobre o npm e também consideraremos os recursos dos package-lock.json package.json e package-lock.json .




Noções básicas de Npm


Npm (gerenciador de pacotes do nó) é o gerenciador de pacotes do Node.js. Na primeira parte deste material, já mencionamos que agora no npm existem mais de meio milhão de pacotes, o que o torna o maior repositório de código do mundo escrito em um idioma. Isso sugere que no npm você pode encontrar pacotes projetados para resolver praticamente qualquer tarefa.

Inicialmente, o npm foi criado como um sistema de gerenciamento de pacotes para o Node.js, mas hoje também é usado para desenvolver projetos front-end em JavaScript. Para interagir com o registro npm, é usado o comando com o mesmo nome, o que oferece ao desenvolvedor uma enorme quantidade de oportunidades.

PackagesCarregando pacotes


Usando o comando npm , você pode baixar pacotes do registro. Abaixo consideraremos exemplos de seu uso.

▍Instalando todas as dependências do projeto


Se o projeto tiver um arquivo package.json , você poderá instalar todas as dependências desse projeto com o seguinte comando:

 npm install 

Este comando fará o download de tudo o que o projeto precisa e colocará esses materiais na pasta node_modules , criando-o se ele não existir no diretório do projeto.

▍Instalando um pacote separado


Um outro pode ser instalado com o seguinte comando:

 npm install <package-name> 

Muitas vezes você pode ver como esse comando é usado não de uma forma tão simples, mas com alguns sinalizadores. Considere-os:

  • O sinalizador --save permite instalar um pacote e incluir uma entrada sobre ele na seção dependencies do arquivo package.json , que descreve as dependências do projeto. Essas dependências são usadas pelo projeto para implementar sua principal funcionalidade, são instaladas durante sua implantação no servidor (após o lançamento do npm 5, as entradas sobre pacotes instalados na seção dependências são feitas automaticamente e sem o uso desse sinalizador).
  • O --save-dev permite instalar o pacote e adicionar uma entrada sobre ele à seção que contém uma lista de dependências de desenvolvimento (ou seja, pacotes necessários durante o desenvolvimento do projeto, como bibliotecas para teste, mas não são necessárias para sua operação) do arquivo package.json chamado devDependencies .

▍ Atualização do pacote


Para atualizar pacotes, use o seguinte comando:

 npm update 

Após receber este comando, o npm verificará todos os pacotes em busca de novas versões e, se encontrarem novas versões que atendam às restrições de versão do pacote especificadas em package.json , instale-os.

Você também pode atualizar um pacote separado:

 npm update <package-name> 

PloadCarregando pacotes de determinadas versões


Além dos downloads de pacotes padrão, o npm também suporta o download de versões específicas deles. Em particular, pode-se observar que algumas bibliotecas são compatíveis apenas com certas versões grandes de outras bibliotecas, ou seja, se as dependências dessas bibliotecas fossem instaladas sem considerar as versões, isso poderia interromper seu trabalho. A capacidade de instalar uma versão específica de um pacote é útil em situações em que, por exemplo, a última versão deste pacote é bastante adequada para você, mas acontece que há um erro nele. Aguardando o lançamento de uma versão fixa do pacote, você pode usar o lançamento mais antigo, mas estável.

A capacidade de especificar versões específicas das bibliotecas exigidas pelo projeto é útil no desenvolvimento da equipe quando todos os membros da equipe usam exatamente as mesmas bibliotecas. A transição para suas novas versões também é realizada centralmente, fazendo alterações no arquivo de projeto package.json .

Em todos esses casos, a capacidade de especificar as versões do pacote exigidas pelo projeto é extremamente útil. Npm segue o padrão de controle de versão semântico (semver).

Executar scripts


O arquivo package.json suporta a capacidade de descrever comandos (scripts) que podem ser iniciados usando esta construção:

 npm <task-name> 

Por exemplo, eis a aparência da lista de scripts na seção correspondente do arquivo:

 { "scripts": {   "start-dev": "node lib/server-development",   "start": "node lib/server-production" } } 

É muito comum usar esse recurso para iniciar o Webpack:

 { "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", } } 

Essa abordagem permite substituir a entrada de comandos longos, repletos de erros, pelas seguintes construções simples:

 $ npm watch $ npm dev $ npm prod 

Here Onde o npm instala pacotes?


Ao instalar pacotes usando o npm (ou yarn ), duas opções de instalação estão disponíveis: local e global.

Por padrão, quando você usa um comando como npm install lodash , o pacote aparece na pasta node_modules localizada na pasta do projeto. Além disso, se o comando acima foi executado, o npm também adicionará uma entrada para a biblioteca lodash à seção de dependencies do arquivo package.json , que está no diretório atual.

A instalação global de pacotes é realizada usando o sinalizador -g :

 npm install -g lodash 

Ao executar esse comando, o npm não instala o pacote na pasta local do projeto. Em vez disso, ele copia os arquivos do pacote para algum local global. Para onde exatamente esses arquivos vão?

Para descobrir, use o seguinte comando:

 npm root -g 

No macOS ou Linux, os arquivos do pacote podem aparecer no /usr/local/lib/node_modules . No Windows, pode ser algo como C:\Users\YOU\AppData\Roaming\npm\node_modules .

No entanto, se você usar o Node.js nvm para controle de versão, o caminho para a pasta do pacote global poderá ser alterado.

Por exemplo, eu uso o nvm, e o comando acima me diz que os pacotes globais estão instalados neste endereço: /Users/flavio/.nvm/versions/node/v8.9.0/lib/node_modules .

AndUse e execute pacotes instalados com o npm


Como usar os módulos instalados usando o npm, local ou globalmente, caindo nas pastas node_modules ? Suponha que você instalou a popular biblioteca lodash , que contém muitas funções auxiliares usadas no desenvolvimento do JavaScript:

 npm install lodash 

Esse comando instalará a biblioteca na pasta local do projeto node_modules .

Para usá-lo em seu código, apenas importe-o usando o comando require :

 const _ = require('lodash') 

E se o pacote for um arquivo executável?

Nesse caso, o arquivo executável node_modules/.bin/ folder na node_modules/.bin/ folder .

Você pode ver como esse mecanismo funciona instalando o pacote cowsay . É um programa em quadrinhos escrito para a linha de comando. Se você passar algum texto para esse pacote, no console, no estilo da arte ASCII, será exibida uma imagem de uma vaca que "pronuncia" o texto correspondente. Outras criaturas podem "expressar" o texto.

Portanto, após instalar o pacote usando o npm install cowsay , ele, juntamente com suas dependências, node_modules em node_modules . E na pasta .bin oculta, serão escritos links simbólicos para arquivos binários cowsay.

Como realizá-los?

Obviamente, você pode digitar algo como ./node_modules/.bin/cowsay no terminal para chamar o programa, esta é uma abordagem funcional, mas é muito melhor usar o npx , uma ferramenta para iniciar executáveis ​​de pacote npm, incluído no npm desde a versão 5.2. Ou seja, no nosso caso, precisamos do seguinte comando:

 npx cowsay 

O caminho para o pacote npx será encontrado automaticamente.

Arquivo Package.json


O arquivo package.json é um elemento essencial de muitos projetos baseados no ecossistema Node.js. Se você programou em JavaScript, seja o desenvolvimento do servidor ou do cliente, provavelmente já viu esse arquivo. Por que é necessário? O que você deve saber sobre ele e que oportunidades ele oferece?

Package.json é um tipo de arquivo de manifesto para um projeto. Ele coloca à disposição do desenvolvedor muitas possibilidades diversas. Por exemplo, ele representa o repositório central de configurações das ferramentas usadas no projeto. Além disso, é o local em que o npm e o yarn gravam informações sobre os nomes e versões dos pacotes instalados.

▍ Estrutura do arquivo


Aqui está um exemplo de um arquivo package.json simples:

 { } 

Como você pode ver, está vazio. Não há requisitos estritos sobre o que deve estar presente em um arquivo para um determinado aplicativo. O único requisito para a estrutura do arquivo é que ele siga as regras do formato JSON. Caso contrário, esse arquivo não poderá ser lido por programas que tentam acessar seu conteúdo.

Se você criar um pacote Node.js. que pretende distribuir através do npm, tudo mudará radicalmente, e o seu package.json deverá ter um conjunto de propriedades que ajudarão outras pessoas a usar o pacote. Falaremos mais sobre isso mais tarde.

Aqui está outro exemplo package.json :

 { "name": "test-project" } 

Ele define a propriedade name , cujo valor é o nome do aplicativo ou pacote cujos materiais estão contidos na mesma pasta em que esse arquivo está localizado.

Aqui está um exemplo mais complicado que tirei de um aplicativo de exemplo escrito usando o Vue.js:

 { "name": "test-project", "version": "1.0.0", "description": "A Vue.js project", "main": "src/main.js", "private": true, "scripts": {   "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",   "start": "npm run dev",   "unit": "jest --config test/unit/jest.conf.js --coverage",   "test": "npm run unit",   "lint": "eslint --ext .js,.vue src test/unit",   "build": "node build/build.js" }, "dependencies": {   "vue": "^2.5.2" }, "devDependencies": {   "autoprefixer": "^7.1.2",   "babel-core": "^6.22.1",   "babel-eslint": "^8.2.1",   "babel-helper-vue-jsx-merge-props": "^2.0.3",   "babel-jest": "^21.0.2",   "babel-loader": "^7.1.1",   "babel-plugin-dynamic-import-node": "^1.2.0",   "babel-plugin-syntax-jsx": "^6.18.0",   "babel-plugin-transform-es2015-modules-commonjs": "^6.26.0",   "babel-plugin-transform-runtime": "^6.22.0",   "babel-plugin-transform-vue-jsx": "^3.5.0",   "babel-preset-env": "^1.3.2",   "babel-preset-stage-2": "^6.22.0",   "chalk": "^2.0.1",   "copy-webpack-plugin": "^4.0.1",   "css-loader": "^0.28.0",   "eslint": "^4.15.0",   "eslint-config-airbnb-base": "^11.3.0",   "eslint-friendly-formatter": "^3.0.0",   "eslint-import-resolver-webpack": "^0.8.3",   "eslint-loader": "^1.7.1",   "eslint-plugin-import": "^2.7.0",   "eslint-plugin-vue": "^4.0.0",   "extract-text-webpack-plugin": "^3.0.0",   "file-loader": "^1.1.4",   "friendly-errors-webpack-plugin": "^1.6.1",   "html-webpack-plugin": "^2.30.1",   "jest": "^22.0.4",   "jest-serializer-vue": "^0.3.0",   "node-notifier": "^5.1.2",   "optimize-css-assets-webpack-plugin": "^3.2.0",   "ora": "^1.2.0",   "portfinder": "^1.0.13",   "postcss-import": "^11.0.0",   "postcss-loader": "^2.0.8",   "postcss-url": "^7.2.1",   "rimraf": "^2.6.0",   "semver": "^5.3.0",   "shelljs": "^0.7.6",   "uglifyjs-webpack-plugin": "^1.1.1",   "url-loader": "^0.5.8",   "vue-jest": "^1.0.2",   "vue-loader": "^13.3.0",   "vue-style-loader": "^3.0.1",   "vue-template-compiler": "^2.5.2",   "webpack": "^3.6.0",   "webpack-bundle-analyzer": "^2.9.0",   "webpack-dev-server": "^2.9.1",   "webpack-merge": "^4.1.0" }, "engines": {   "node": ">= 6.0.0",   "npm": ">= 3.0.0" }, "browserslist": [   "> 1%",   "last 2 versions",   "not ie <= 8" ] } 

Como você pode ver, há muitas coisas interessantes. Nomeadamente, as seguintes propriedades podem ser distinguidas aqui:

  • name - define o nome do aplicativo (pacote).
  • version - contém informações sobre a versão atual do aplicativo.
  • description - uma breve descrição do aplicativo.
  • main - define o ponto de entrada para o aplicativo.
  • private - se essa propriedade estiver configurada como true , isso impede que o pacote seja publicado acidentalmente para npm.
  • scripts - define um conjunto de scripts do Node.js. que podem ser executados.
  • dependencies - contém uma lista de pacotes npm dos quais o aplicativo depende.
  • devDependencies - contém uma lista de pacotes npm usados ​​no desenvolvimento de um projeto, mas não quando ele realmente funciona.
  • engines - define a lista de versões do Node.js. nas quais o aplicativo é executado.
  • lista de navegadores - usada para armazenar a lista de navegadores (e suas versões) que o aplicativo deve suportar.

Todas essas propriedades são usadas pelo npm ou por outras ferramentas usadas durante o ciclo de vida do aplicativo.

UsedPropriedades usadas no pacote.json


Vamos falar sobre as propriedades que podem ser usadas no package.json . Aqui usaremos o termo "pacote", mas tudo o que é dito sobre pacotes também é verdadeiro para aplicativos locais que não estão planejados para serem usados ​​como pacotes.

A maioria das propriedades que descrevemos são usadas apenas para as necessidades do repositório npm, algumas são usadas por programas que interagem com o código como o mesmo npm.

Propriedade de nome


A propriedade name define o nome do pacote:

 "name": "test-project" 

O nome deve ter menos de 214 caracteres, não deve incluir espaços, deve conter apenas letras maiúsculas, hífens ( - ) e sublinhados ( _ ).

Restrições semelhantes existem porque, quando um pacote é publicado no npm, seu nome é usado para formar a URL da página do pacote.

Se você publicou o código do pacote no GitHub, em domínio público, uma boa opção para o nome do pacote é o nome do repositório GitHub correspondente.

Propriedade do autor


A propriedade author contém informações sobre o autor do pacote:

 { "author": "Flavio Copes <flavio@flaviocopes.com> (https://flaviocopes.com)" } 

Pode ser apresentado no seguinte formato:

 { "author": {   "name": "Flavio Copes",   "email": "flavio@flaviocopes.com",   "url": "https://flaviocopes.com" } } 

Propriedade de colaboradores


A propriedade contributors contém uma matriz com informações sobre as pessoas que contribuíram para o projeto:

 { "contributors": [   "Flavio Copes <flavio@flaviocopes.com> (https://flaviocopes.com)" ] } 

Esta propriedade pode ser assim:

 { "contributors": [   {     "name": "Flavio Copes",     "email": "flavio@flaviocopes.com",     "url": "https://flaviocopes.com"   } ] } 

Propriedade de erros


A propriedade bugs contém um link para o rastreador de erros do projeto. É muito provável que esse link leve à página do sistema de rastreamento de erros do GitHub:

 { "bugs": "https://github.com/flaviocopes/package/issues" } 

Propriedade da página inicial


A propriedade da homepage permite definir a página inicial do pacote:

 { "homepage": "https://flaviocopes.com/package" } 

Propriedade de versão


A propriedade version contém informações sobre a versão atual do pacote:

 "version": "1.0.0" 

Ao formar o valor dessa propriedade, você deve seguir as regras do controle de versão semântico . Isso significa, em particular, que o número da versão é sempre representado por três dígitos: xxx

O primeiro número é a versão principal do pacote, o segundo é a versão secundária e o terceiro é a versão do patch.

Alterar esses números tem um certo significado. Portanto, o lançamento de um pacote no qual os erros são corrigidos apenas leva a um aumento no valor da versão do patch. Se um pacote for lançado, as alterações feitas com compatibilidade retroativa com a versão anterior, a versão secundária será alterada. As versões principais dos pacotes podem conter alterações que os tornam incompatíveis com os pacotes das versões principais anteriores.

Propriedade da licença


A propriedade license contém informações sobre a license pacote:

 "license": "MIT" 

Propriedade de palavras-chave


A propriedade keywords contém uma matriz de palavras-chave relacionadas à funcionalidade do pacote:

 "keywords": [ "email", "machine learning", "ai" ] 

A seleção correta de palavras-chave ajuda as pessoas a encontrar o que precisam ao procurar pacotes para resolver certos problemas, permite agrupar pacotes e avaliar rapidamente suas possíveis funcionalidades ao visualizar o site npm.

Propriedade Descrição


A propriedade description contém uma breve descrição do pacote:

 "description": "A package to work with strings" 

Essa propriedade é especialmente importante se você planeja publicar o pacote no npm, pois permite que os usuários do site npm entendam a finalidade do pacote.

Propriedade de repositório


A propriedade repository indica onde o repositório do pacote está localizado:

 "repository": "github:flaviocopes/testing", 

Observe que o valor dessa propriedade possui o prefixo github . O Npm também suporta prefixos para alguns outros serviços populares desse tipo:

 "repository": "gitlab:flaviocopes/testing", "repository": "bitbucket:flaviocopes/testing", 

O sistema de controle de versão usado no desenvolvimento do pacote também pode ser definido explicitamente:

 "repository": { "type": "git", "url": "https://github.com/flaviocopes/testing.git" } 

O mesmo pacote pode usar sistemas de controle de versão diferentes:

 "repository": { "type": "svn", "url": "..." } 

Propriedade principal


A propriedade main define o ponto de entrada para o pacote:

 "main": "src/main.js" 

Quando um pacote é importado para o aplicativo, é nesse local que a pesquisa será realizada para o que o módulo correspondente exporta.

Propriedade privada


A propriedade private configurada como true impede que o pacote seja publicado acidentalmente no npm:

 "private": true 

Propriedade de scripts


A propriedade scripts define a lista de scripts ou utilitários que podem ser ativados usando as ferramentas npm:

 "scripts": { "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", "start": "npm run dev", "unit": "jest --config test/unit/jest.conf.js --coverage", "test": "npm run unit", "lint": "eslint --ext .js,.vue src test/unit", "build": "node build/build.js" } 

Esses scripts são aplicativos de linha de comando. Você pode executá-los usando npm ou yarn, respectivamente, executando comandos no formato npm run XXXX ou yarn XXXX , em que XXXX é o nome do script. Por exemplo, pode ser assim:

 npm run dev 

Os scripts podem ser chamados como você quiser, eles podem fazer quase tudo o que um desenvolvedor pode querer.

Propriedade de dependências


A propriedade dependencies contém uma lista de pacotes npm instalados como dependências de pacotes:

 "dependencies": { "vue": "^2.5.2" } 

Ao instalar um pacote usando npm ou yarn, os seguintes comandos são usados:

 npm install <PACKAGENAME> yarn add <PACKAGENAME> 

Esses pacotes são adicionados automaticamente à lista de dependências do pacote que está sendo desenvolvido.

Propriedade DevDependencies


A propriedade devDependencies contém uma lista de pacotes npm instalados como dependências de desenvolvimento:

 "devDependencies": { "autoprefixer": "^7.1.2", "babel-core": "^6.22.1" } 

Essa lista é diferente daquela armazenada na propriedade dependencies , uma vez que os pacotes disponíveis nela são instalados apenas no sistema do desenvolvedor do pacote; no uso prático do pacote, eles não são usados.

Os pacotes entram nessa lista quando são instalados usando npm ou yarn, da seguinte maneira:

 npm install --dev <PACKAGENAME> yarn add --dev <PACKAGENAME> 

Propriedade de motores


A propriedade engines indica quais versões do Node.js e outros produtos de software são usados ​​para fornecer o pacote:

 "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0", "yarn": "^0.13.0" } 

Propriedade da lista de navegadores


A propriedade browserlist permite que browserlist relate quais navegadores (e suas versões) serão suportados pelo desenvolvedor do pacote:

 "browserslist": [ "> 1%", "last 2 versions", "not ie <= 8" ] 

Esta propriedade é usada pelo Babel, Autoprefixer e outras ferramentas. A análise desta lista permite que eles adicionem ao pacote apenas os polyfills e mecanismos auxiliares necessários para os navegadores listados.

O valor da propriedade da lista de navegadores mostrada aqui como exemplo significa que você deseja oferecer suporte a pelo menos duas versões principais de todos os navegadores com pelo menos 1% de uso (esses dados são obtidos no CanIUse.com ), com exceção do IE 8 e versões mais antigas deste navegador (mais isso pode ser encontrado na página do pacote de listas de navegadores ).

InArmazenamento nas configurações do package.json para várias ferramentas de software


No package.json você pode armazenar configurações para várias ferramentas auxiliares como Babel ou ESLint.

Cada uma dessas ferramentas possui uma propriedade especial, como eslintConfig ou babel . Detalhes sobre o uso de tais propriedades podem ser encontrados na documentação dos respectivos projetos.

▍Sobre versões de pacotes e controle de versão semântico


, , , . , ~3.0.0 ^0.13.0 . , , .

, , , , :

  • ~ : ~0.13.0 , - . , 0.13.1 , 0.14.0 — .
  • ^ : ^0.13.0 , , - . , 0.13.1 , 0.14.0 , .
  • * : , , , — .
  • > : , .
  • >= : , .
  • <= : , .
  • < : , .
  • = : .
  • - : , — 2.1.0 - 2.6.2 .
  • || : , . < 2.1 || > 2.6 .

:

  • : , , - .
  • latest : , .

, , -. , 1.0.0 || >=1.1.0 <1.2.0 , 1.0.0 , , 1.1.0 , 1.2.0 .

package-lock.json


package-lock.json npm 5. Node.js-. ? , package.json , .

, , , , .

, package.json . package.json , (- ) .

Git node_modules , . , npm install , , , ~ , -, , , -.

^ . , , , .

, - , npm install . , . , , - , , , ( ) .

package-lock.json npm npm install .

, , ( Composer PHP) .

package-lock.json Git-, , , , , Git .

package-lock.json npm update .

▍ package-lock.json


package-lock.json , cowsay, npm install cowsay :

 { "requires": true, "lockfileVersion": 1, "dependencies": {   "ansi-regex": {     "version": "3.0.0",     "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3. 0.0.tgz",     "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="   },   "cowsay": {     "version": "1.3.1",     "resolved": "https://registry.npmjs.org/cowsay/-/cowsay-1.3.1.tgz" ,     "integrity": "sha512-3PVFe6FePVtPj1HTeLin9v8WyLl+VmM1l1H/5P+BTTDkM Ajufp+0F9eLjzRnOHzVAYeIYFF5po5NjRrgefnRMQ==",     "requires": {       "get-stdin": "^5.0.1",       "optimist": "~0.6.1",       "string-width": "~2.1.1",       "strip-eof": "^1.0.0"     }   },   "get-stdin": {     "version": "5.0.1",     "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0. 1.tgz",     "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g="   },   "is-fullwidth-code-point": {     "version": "2.0.0",     "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/ is-fullwidth-code-point-2.0.0.tgz",     "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="   },   "minimist": {     "version": "0.0.10",     "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10 .tgz",     "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8="   },   "optimist": {     "version": "0.6.1",     "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",     "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=",     "requires": {       "minimist": "~0.0.1",       "wordwrap": "~0.0.2"     }   },   "string-width": {     "version": "2.1.1",     "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",     "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",     "requires": {       "is-fullwidth-code-point": "^2.0.0",       "strip-ansi": "^4.0.0"     }   },   "strip-ansi": {     "version": "4.0.0",     "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",     "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",     "requires": {       "ansi-regex": "^3.0.0"     }   },   "strip-eof": {     "version": "1.0.0",     "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",     "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="   },   "wordwrap": {     "version": "0.0.3",     "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",     "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc="   } } } 

. cowsay, :

  • get-stdin
  • optimist
  • string-width
  • strip-eof

, , , requires , :

  • ansi-regex
  • is-fullwidth-code-point
  • minimist
  • wordwrap
  • strip-eof

, version , resolved , , integrity , .


npm package.json package-lock.json . npm npx.

Caros leitores! — npm yarn?

Source: https://habr.com/ru/post/pt423703/


All Articles