Curso de entrada ao domínio de front-end (vue): Entrando no aprendizado
Hoje em dia, os alunos de desenvolvimento de front-end não podem prescindir do npm
, um excelente mecanismo de gerenciamento de versão de pacote que transporta toda a próspera comunidade NodeJS
. entender seu mecanismo interno Isso ajuda a aprofundar nossa compreensão do desenvolvimento de módulos e de várias configurações de engenharia de front-end para acelerar nossa solução de problemas (acredito que muitos alunos tiveram problemas com vários problemas de dependência).
Este artigo conduz uma análise detalhada do mecanismo de gerenciamento de pacotes do npm
sob três perspectivas: package.json
, gerenciamento de versões, instalação de dependências e exemplos específicos.
No Node.js
, um módulo é uma biblioteca ou framework e também um projeto Node.js
O projeto Node.js
segue uma arquitetura modular. Quando criamos um projeto Node.js
, significa criar um módulo. Este módulo deve ter um arquivo de descrição, ou seja, package.json
. É nosso arquivo de configuração mais comum, mas você realmente entendeu detalhadamente a configuração nele? A configuração de um arquivo package.json
razoável determina diretamente a qualidade do nosso projeto, então primeiro analisaremos a configuração detalhada de package.json
.
Existem muitos atributos em package.json
, dos quais apenas dois devem ser preenchidos: name
e version
. Esses dois atributos formam o identificador exclusivo de um módulo npm
.
name
é o nome do módulo Ao nomear, você precisa seguir algumas especificações e recomendações oficiais:
url
nome do pacote se tornará um parâmetro na url
do módulo, na linha de comando ou em um nome de pasta. estão no nome do pacote. Nenhum dos dois pode ser usado. Você pode usar validate-npm-package-name
para verificar se o nome do pacote é legal.
Nomes de pacotes semânticos podem ajudar os desenvolvedores a encontrar os pacotes necessários com mais rapidez e evitar a obtenção acidental do pacote errado.
Se houver alguns símbolos no nome do pacote, os símbolos não devem ser repetidos com o nome do pacote existente após removê-los.
Por exemplo: como react-native
já existe, react.native
e reactnative
não podem ser criados novamente.
Por exemplo: o nome de usuário é conard
, então o escopo é @conard
, e o pacote publicado pode ser @conard/react
.
name
é o identificador exclusivo de um pacote e não deve ser repetido com outros nomes de pacotes. Podemos executar npm view packageName
para ver se o pacote está ocupado e podemos ver algumas informações básicas sobre ele:
Se o nome do pacote nunca tiver sido usado, um erro 404
será gerado:
Além disso, você também pode acessar https://www.npmjs.com/
para obter informações mais detalhadas sobre o pacote.
{ "description": "Uma linguagem de design de UI de classe empresarial e implementação de componentes React", "palavras-chave": [ "formiga", "componente", "componentes", "projeto", "estrutura", "front-end", "reagir", "componente de reação", "ui" ] }
description
é usado para adicionar informações de descrição do módulo para facilitar que outras pessoas entendam seu módulo.
keywords
é usado para adicionar palavras-chave ao seu módulo.
Claro, eles também desempenham um papel muito importante, que é facilitar a recuperação do módulo. Quando você usa npm search
para recuperar um módulo, ele corresponderá description
e keywords
. Escrever uma boa description
e keywords
ajudará seu módulo a obter uma exposição cada vez mais precisa:
descreverem os desenvolvedores: author
e contributors
author
refere-se ao autor principal do pacote e um author
corresponde a uma pessoa. contributors
refere-se às informações do contribuidor. Um contributors
corresponde a vários contribuidores. O valor é uma matriz. A descrição da pessoa pode ser uma string ou a seguinte estrutura:
{ "nome" : "ConardLi", "e-mail": "[email protected]", "url": "https://github.com/ConardLi" }
{ "página inicial": "http://ant.design/", "insetos": { "url": "https://github.com/ant-design/ant-design/issues" }, "repositório": { "tipo": "git", "url": "https://github.com/ant-design/ant-design" }, }
homepage
é usado para especificar a página inicial deste módulo.
repository
é usado para especificar o repositório de código do módulo.
bugs
especifica um endereço ou e-mail onde as pessoas que têm dúvidas sobre o seu módulo podem ir aqui para tirar dúvidas.
Nosso projeto pode depender de um ou mais pacotes de dependências externas De acordo com os diferentes usos dos pacotes de dependências, nós os configuramos sob os seguintes atributos: dependencies、devDependencies、peerDependencies、bundledDependencies、optionalDependencies
.
Antes de apresentar diversas configurações de dependências, primeiro vamos dar uma olhada nas regras de configuração de dependências. A configuração do pacote de dependências que você vê pode ser a seguinte:
"dependências": {. "antd": "ant-design/ant-design#4.0.0-alpha.8", "axios": "^1.2.0", "test-js": "arquivo:../teste", "test2-js": "http://cdn.com/test2-js.tar.gz", "core-js": "^1.1.5", }
A configuração de dependência segue as seguintes regras de configuração:
依赖包名称:VERSION
VERSION
é uma configuração de número de versão que segue SemVer
. Quando npm install
ele irá para o servidor npm para baixar pacotes que atendam ao intervalo de versão especificado.依赖包名称:DWONLOAD_URL
DWONLOAD_URL
é um endereço de pacote compactado tarball
para download. Quando o módulo for instalado, este .tar
será baixado e instalado localmente.依赖包名称:LOCAL_PATH
LOCAL_PATH
é um caminho de pacote de dependência local, como file:../pacakges/pkgName
. Adequado para você testar um pacote npm
localmente, este método não deve ser aplicado online.依赖包名称:GITHUB_URL
GITHUB_URL
é o método de escrita do username/modulename
do github
, por exemplo: ant-design/ant-design
. Você também pode especificar tag
e commit id
posteriormente.依赖包名称:GIT_URL
GIT_URL
é git url
da nossa base de código clone usual, que segue o seguinte formato:<protocolo>://[<usuário>[:<senha>]@]<hostname>[:<porta>] [: ][/]<path>[#<commit-ish> | #semver:<semver>]
protocal
pode estar nos seguintes formatos:
git://github.com/user/project.git#commit-ish
git+ssh://user@hostname:project.git#commit-ish
git+ssh://user@hostname/project.git#commit-ish
git+http://user@hostname/project/blah.git#commit-ish
git+https://user@hostname/project/blah.git#commit-ish
dependencies
os módulos dos quais o projeto depende. Tanto o ambiente de desenvolvimento quanto os módulos de dependência do ambiente de produção podem ser configurados aqui, como
". dependências": { "lodash": "^4.17.13", "momento": "^2.24.0", }Existem alguns pacotes em
que você só pode usar no ambiente de desenvolvimento, como eslint
para verificar especificações de código e jest
para teste. Quando os usuários usam seu pacote, ele pode rodar normalmente mesmo sem instalar essas dependências. levará mais tempo e recursos, então você pode adicionar essas dependências a devDependencies
. Essas dependências ainda serão instaladas e gerenciadas quando você executar npm install
localmente, mas não serão instaladas no ambiente de produção:
"devDependencies" : { "brincadeira": "^24.3.1", "eslint": "^6.1.0", }
peerDependencies
são usados para especificar a versão da qual depende o módulo que você está desenvolvendo e a compatibilidade da versão do pacote dependente instalada pelo usuário.
A afirmação acima pode ser um pouco abstrata. Vamos tomar ant-design
como exemplo. package.json
do ant-design
tem a seguinte configuração:
"peerDependencies": {. "reagir": ">=16.0.0", "react-dom": ">=16.0.0" }
Ao desenvolver um sistema e usar ant-design
, você definitivamente precisa confiar no React
. Ao mesmo tempo, ant-design
também precisa contar com React
. React
necessária para manter a operação estável é 16.0.0
, e a versão React
na qual você confia ao desenvolver é 15.x
:
no momento, ant-design
precisa usar React
e importá-lo:
import * as React from 'react'; import * as ReactDOM from 'react-dom'
O que você obtém neste momento é o ambiente host, que é a versão React
em seu ambiente, o que pode causar alguns problemas. Em npm2
, especificar peerDependencies
acima significará forçar o ambiente host a instalar versões de react@>=16.0.0和react-dom@>=16.0.0
.
No futuro, npm3
não exigirá mais que os pacotes de dependência especificados por peerDependencies
sejam instalados à força. Pelo contrário npm3
verificará se a instalação está correta após a conclusão da instalação. .
"dependências": { "reagir": "15.6.0", "antd": "^3.22.0" }
Por exemplo, confio na versão mais recente do antd
no projeto e, em seguida, confio na versão 15.6.0
do react
. O seguinte aviso será dado ao instalar a dependência:
Em alguns cenários, o pacote dependente pode não ser uma dependência forte. A função deste pacote dependente é dispensável. Quando este pacote dependente não pode ser obtido, você deseja que npm install
continue em execução sem causar falha. optionalDependencies
. Observe que a configuração em optionalDependencies
substituirá dependencies
portanto, ela só precisa ser configurada em um local.
É claro que ao referenciar dependências instaladas em optionalDependencies
, o tratamento de exceções deve ser feito, caso contrário um erro será relatado quando o módulo não puder ser obtido.
é diferente do valor acima. O valor de bundledDependencies
é uma matriz. Alguns módulos podem ser especificados na matriz. Esses módulos serão empacotados juntos quando este pacote for lançado.
"bundledDependencies": ["pacote1", "pacote2"]
{ "licença": "MIT" }
O campo license
é usado para especificar o contrato de código aberto do software. O contrato de código aberto detalha os direitos que outras pessoas têm após obter seu código, quais operações elas podem realizar em seu código e quais operações são proibidas. Existem muitas variantes do mesmo acordo. Um acordo demasiado vago fará com que o autor perca muitos direitos sobre a obra, enquanto um acordo demasiado rigoroso não será conveniente para a utilização e divulgação da obra pelos utilizadores. , os autores de código aberto devem considerar quais direitos desejam manter e quais restrições desejam afrouxar.
Os contratos de software podem ser divididos em duas categorias: código aberto e comerciais. Para acordos comerciais, também chamados de declarações legais e contratos de licença, cada software terá seu próprio conjunto de textos, escritos pelo autor do software ou por um advogado especializado. não há necessidade de fazer isso sozinho. Escolher uma licença de código aberto amplamente divulgada é uma boa escolha.
A seguir estão vários protocolos de código aberto convencionais:
MIT
: Contanto que os usuários incluam um aviso de direitos autorais e um aviso de licença em suas cópias do projeto, eles poderão fazer o que quiserem com seu código sem qualquer responsabilidade de sua parte.Apache
: Semelhante ao MIT
, mas também inclui termos relacionados ao licenciamento de patentes fornecidas por contribuidores aos usuários.GPL
: Os usuários que modificam o código do projeto devem publicar suas modificações relevantes ao redistribuir o código-fonte ou o código binário.Se você tiver requisitos mais detalhados para o contrato de código aberto, acesse Choosealicense.com/ para obter uma descrição mais detalhada do contrato de código aberto.
1.5{ "principal": "lib/index.js", }
O atributo main
pode especificar o arquivo de entrada principal do programa. Por exemplo, a entrada do módulo lib/index.js
especificada por antd
acima, quando introduzimos antd
no código: import { notification } from 'antd';
o que é introduzido é lib/index.js
.
Quando seu módulo é uma ferramenta de linha de comandos, você precisa especificar uma entrada para a ferramenta de linha de comandos, ou seja, especificar a correspondência entre seu nome de comando e o arquivo local especificável. Se instalado globalmente, o npm usará um link simbólico para vincular o arquivo executável a /usr/local/bin
. Se instalado localmente, ele será vinculado a ./node_modules/.bin/
.
{ "lixo": { "conard": "./bin/index.js" } }
Por exemplo, a configuração acima: Quando seu pacote é instalado globalmente: npm
criará um link virtual chamado conard
em /usr/local/bin
, apontando para "./bin/index.js"
. Neste momento, se você executar conard
na linha de comando, o arquivo js vinculado será chamado.
Não entrarei em muitos detalhes aqui; mais conteúdo será explicado em detalhes em meus artigos subsequentes sobre ferramentas de linha de comando.
{ "arquivos": [ "dist", "lib", "é" ] }
O atributo files
é usado para descrever a lista de arquivos que você envia para o servidor npm
após npm publish
. Se você especificar uma pasta, todo o conteúdo da pasta será incluído. Podemos ver que o pacote baixado possui a seguinte estrutura de diretórios:
Além disso, você também pode configurar um arquivo
.npmignore
para excluir alguns arquivos para.gitignore
que um grande número de arquivos inúteis sejam enviados paranpm
. Arquivos.gitignore
também podem atuar como arquivos.npmignore
.
O comando man
é um comando de ajuda no Linux
. Através do comando man
, você pode visualizar a ajuda do comando, ajuda do arquivo de configuração, ajuda de programação e outras informações no Linux
.
Se o seu módulo node.js
for uma ferramenta de linha de comando global, você poderá especificar o endereço do documento pesquisado pelo comando man
por meio do atributo man
em package.json
.
Os arquivos man
devem terminar com um número ou, se compactados, .gz
. O número indica em qual parte do man
o arquivo será instalado. Se o nome do arquivo man
não começar com o nome do módulo, o nome do módulo será prefixado durante a instalação.
Por exemplo, a seguinte configuração:
{ "homem" : [ "/Users/isaacs/dev/npm/cli/man/man1/npm-access.1", "/Users/isaacs/dev/npm/cli/man/man1/npm-audit.1" ] }
Insira man npm-audit
na linha de comando:
Um módulo node.js
é implementado com base CommonJS
Em estrita conformidade com a especificação CommonJS
, além do arquivo de descrição do pacote package.json
, o diretório do módulo também precisa conter os seguintes diretórios:
bin
: onde. arquivos binários executáveis são armazenados. Diretóriolib
: Diretório para armazenar o código jsdoc
: Diretório para armazenar documentostest
: Diretório para armazenar o código do caso de teste de unidadeNo diretório do módulo, você não pode seguir estritamente a estrutura acima para organizá-lo ou nomeá-lo. . Você pode especificar directories
em package.json
Properties para especificar como sua estrutura de diretórios corresponde à estrutura canônica acima. Além disso, o atributo directories
não possui outras aplicações por enquanto.
{ "diretórios": { "lib": "src/lib/", "bin": "src/bin/", "homem": "src/homem/", "doc": "src/doc/", "exemplo": "src/exemplo/" } }
No entanto, o documento oficial afirma que embora este atributo atualmente não tenha um papel importante, alguns truques poderão ser desenvolvidos no futuro. Por exemplo, arquivos markdown armazenados em doc e arquivos de exemplo armazenados em example poderão ser exibidos de maneira amigável.
{ "roteiros": { "teste": "jest --config .jest.js --no-cache", "dist": "antd-tools executa dist", "compile": "antd-tools executa compilação", "build": "npm run compile && npm run dist" } }
scripts
são usados para configurar as abreviaturas de alguns comandos de script. Cada script pode ser usado em combinação entre si. Esses scripts podem cobrir todo o ciclo de vida do projeto, eles podem ser chamados usando npm run command
. Se for uma palavra-chave npm
, ela poderá ser chamada diretamente. Por exemplo, a configuração acima especifica os seguintes comandos: npm run test
, npm run dist
, npm run compile
, npm run build
.
O campo config
é usado para configurar as variáveis de ambiente usadas no script. Por exemplo, a configuração a seguir pode ser obtida usando process.env.npm_package_config_port
no script.
{ "config": { "porta": "8080" } }
Se seu módulo node.js
for usado principalmente para instalar ferramentas de linha de comando globais, esse valor será definido como true
e os usuários receberão um aviso quando instalarem o módulo localmente. Esta configuração não impedirá a instalação dos usuários, mas solicitará que os usuários evitem o uso incorreto que pode causar alguns problemas.
Se o atributo private
for definido como true
, o npm se recusará a publicá-lo. Isso evita que um módulo privado seja publicado acidentalmente.
"publishConfig": { "registro": "https://registry.npmjs.org/" },
configuração mais detalhada ao publicar o módulo, por exemplo, você pode configurar para publicar apenas uma determinada tag
, configurar a fonte npm
privada para publicar.
uma configuração mais detalhada, consulte npm-config
Se você desenvolver um módulo que só pode ser executado no sistema darwin
, você precisa garantir que os usuários windows
não instalarão seu módulo para evitar erros desnecessários.
Usar o atributo os
pode ajudá-lo a cumprir os requisitos acima. Você pode especificar que seu módulo só pode ser instalado em determinados sistemas ou especificar uma lista negra de sistemas que não podem ser instalados:
"os" : [ "darwin", "linux" ] "os" : [ "!win32" ]
Por exemplo, atribuo um módulo de teste a uma lista negra do sistema: "os" : [ "!darwin" ]
. Quando eu o instalo neste sistema, o seguinte erro aparecerá:
No ambiente do nó, é possível usar process.platform para determinar o sistema operacional.
é semelhante ao os
acima. Podemos usar o atributo cpu
para limitar com mais precisão o ambiente de instalação do usuário:
"cpu" : [ "x64", "ia32" ] "cpu" : [ "!arm", "!mips" ]
No ambiente do nó, você pode usar process.arch para determinar a arquitetura da CPU.
O sucesso do Nodejs
é inseparável do excelente sistema de gerenciamento de dependências do npm
. Antes de apresentar todo o sistema de dependências, você deve entender como npm
gerencia as versões dos pacotes dependentes. Este capítulo apresentará as especificações de lançamento de versão dos npm包
, como gerenciar as versões de vários pacotes dependentes e algumas práticas recomendadas em relação às versões dos pacotes.
Você pode executar npm view package version
para visualizar a versão mais recente de um package
.
Execute npm view conard versions
para visualizar todas as versões publicadas de um package
no servidor npm.
Execute npm ls
para visualizar as informações de versão de todos os pacotes na árvore de dependências do warehouse atual.
As versões dos módulos em npm包
precisam seguir SemVer
- uma regra de representação de número de versão unificada e orientadora elaborada pelo Github
. Na verdade, é a abreviatura de Semantic Version
.
Site oficial da especificação SemVer: https://semver.org/Standard
O número de versão padrão da especificação SemVer
adota o formato XYZ
, onde X, Y e Z são inteiros não negativos e o preenchimento de zero na frente dos números é Entrada. X é o número da versão principal, Y é o número da versão secundária e Z é o número da revisão. Cada elemento deve ser incrementado numericamente.
major
): Quando você faz modificações incompatíveis na APIminor
): Quando você cria funcionalidades compatíveis com versões anteriores Novopatch
): Quando você faz problemas de compatibilidade com versões anteriores Correção.Por exemplo: 1.9.1 -> 1.10.0 -> 1.11.0
Quando uma versão tem grandes alterações, não é estável e pode não atender aos requisitos de compatibilidade esperados, você pode lançar uma versão avançada primeiro.
O número da versão inicial pode ser adicionado ao final de "número da versão principal. número da versão secundária. número de revisão". Primeiro adicione um número de conexão e, em seguida, uma série de identificadores e informações de compilação de versão separados por pontos.
alpha
):beta
):rc
Release candiate
Vamos dar uma olhada nas versões históricas do React
:
Pode-se observar que a versão é lançada estritamente de acordo com SemVer
:
主版本号.次版本号.修订号
A nomenclatura16.8.0 -> 16.8.1 -> 16.8.2
.16.8.0 -> 16.8.1 -> 16.8.2
alpha
beta
, rc
e outras versões avançadas. Depois de modificar certas funções do pacote npm
, geralmente é necessário lançar um. nova versão. Nossa abordagem usual é modificar diretamente package.json
para a versão especificada. Se a operação estiver incorreta, é fácil causar confusão no número da versão. Podemos usar comandos que estejam em conformidade com Semver
para concluir esta operação:
npm version patch
: atualize o número de revisãonpm version minor
: atualize o número da versão secundárianpm version major
: atualize o número de versão principalno desenvolvimento é definitivamente indispensável para a operação de alguns números de versão. Se esses números de versão estiverem em conformidade com a especificação SemVer
, podemos usar o pacote npm semver
para operar versões para nos ajudar. compare tamanhos de versão, extraia informações de versão e outras operações.
O Npm também usa essa ferramenta para lidar com o trabalho de versionamento.
npm install semver
semver.gt('1.2.3', '9.8.7') // false semver.lt('1.2.3', '9.8.7') // true
semver.valid('1.2.3') // '1.2.3' semver.valid('abc') // null
semver.valid(semver.coerce('v2')) // '2.0.0' semver.valid(semver.coerce('42.6.7.9.3-alpha')) //
semver.clean(' =v1.2.3 ') // '1.2.3' semver.satisfies('1.2.3', '1.x || >=2.5.0 || 5.0.0 - 7.2.3') // verdadeiro semver.minVersion('>=1.0.0') // '1.0.0'
Os usos acima são os mais comuns do semver. Para obter mais detalhes, consulte a documentação do semver: https://github.com/npm/node. -semver
Freqüentemente vemos diferentes maneiras de escrever várias dependências em package.json
:
"dependencies": { "sinal": "1.4.0", "figlet": "*", "reagir": "16.x", "tabela": "~5.4.6", "yargs": "^14.0.0" }
Os três primeiros são fáceis de entender:
"signale": "1.4.0"
: Número de versão corrigido"figlet": "*"
: Qualquer versão ( >=0.0.0
)"react": "16.x"
: Match main Version ( >=16.0.0 <17.0.0
)"react": "16.3.x"
: Corresponde à versão principal e à versão secundária ( >=16.3.0 <16.4.0
)Vamos dar uma olhada nas duas últimas, a número da versão Os símbolos ~
e ^
estão entre aspas:
~
: Quando uma nova versão é obtida ao instalar dependências, instale a versão mais recente de z
em xyz
. Ou seja, embora o número da versão principal e o número da versão secundária sejam mantidos inalterados, o número da revisão mais recente é mantido.^
: Quando uma nova versão é obtida ao instalar dependências, y
e z
em xyz
instaladas são as versões mais recentes. Ou seja, mantendo o número da versão principal inalterado, mantenha o número da versão secundária e o número da revisão como a versão mais recente.A dependência mais comum no arquivo package.json
deve ser "yargs": "^14.0.0"
, porque quando usamos npm install package
para instalar o pacote, npm
instala a versão mais recente por padrão e depois a instala no Add um sinal ^
antes do número da versão.
Observe que quando o número da versão principal for 0
, será considerada uma versão instável. A situação é diferente da acima:
0
: ^0.0.z
e ~0.0.z
são ambos. consideradas versões fixas, nenhuma alteração ocorrerá durante a instalação de dependências.0
: ^0.yz
se comporta da mesma forma que ~0.yz
, apenas o número da revisão é mantido como a versão mais recente.O número de versão 1.0.0 é usado para definir a API pública. Quando seu software for lançado no ambiente oficial, ou tiver uma API estável, você poderá lançar a versão 1.0.0. Portanto, quando você decidir lançar uma versão oficial de um pacote npm para o mundo exterior, marque sua versão como 1.0.0.
No desenvolvimento real, problemas estranhos geralmente ocorrem devido a inconsistências em várias dependências ou, em alguns cenários, não queremos que as dependências sejam atualizadas. É recomendado usar package-lock.json
durante o desenvolvimento.
Bloquear a versão da dependência significa que, a menos que executemos atualizações manualmente, a versão corrigida será instalada sempre que instalarmos a dependência. Certifique-se de que toda a equipe use dependências com números de versão consistentes.
Cada vez que você instala uma versão fixa, não há necessidade de calcular o intervalo de versões da dependência, o que pode acelerar bastante o tempo de instalação da dependência na maioria dos cenários.
Ao usar package-lock.json, certifique-se de que a versão npm esteja acima de 5.6, pois entre 5.0 e 5.6, a lógica de processamento de package-lock.json foi atualizada várias vezes e a lógica de pós-processamento da versão 5.6 se estabilizou gradativamente.
Analisaremos a estrutura detalhada de package-lock.json
em capítulos posteriores.
Nosso objetivo de
Em cenários reais de desenvolvimento, embora não precisemos instalar uma nova versão todas as vezes, ainda precisamos atualizar as versões de dependência regularmente para que possamos aproveitar as correções de problemas, melhorias de desempenho e novas atualizações de recursos trazidas pelas atualizações de pacotes de dependência.
Usar npm outdated
pode nos ajudar a listar as dependências que não foram atualizadas para a versão mais recente:
e executar npm update
.
1.0.0
.主版本号.次版本号.修订号
alpha、beta、rc
npm
desenvolvidos por membros da equipe. Neste momento, é recomendado alterar o prefixo da versão ~
. as dependências do projeto principal devem ser atualizadas sempre que as subdependências são atualizadas, o que é muito complicado. Se as subdependências forem completamente confiáveis, abra diretamente ^
Atualize para a versão mais recente sempre.docker
e as subdependências ainda estão sendo desenvolvidas e atualizadas localmente. Antes que a versão docker
seja lançada, todas as versões de dependência devem ser bloqueadas para garantir que não haja problemas online após as subdependências locais serem lançadas. lançado.npm
esteja acima de 5.6
e certifique-se de que o arquivo package-lock.json
esteja habilitado por padrão.npm inatall
é executado pelo membro de inicialização, package-lock.json
é enviado ao warehouse remoto. Não envie node_modules
diretamente para o repositório remoto.npm update
para atualizar as dependências e lock
o arquivo lock
para garantir que outros membros atualizem suas dependências simultaneamente.package.json
e execute npm install
lock
npm install package@version
(alterar package.json
não fará downgrade das dependências).npm install
provavelmente passará pelos processos acima. Este capítulo falará sobre os detalhes de implementação, desenvolvimento e porquê de cada processo.
Todos sabemos que após executar npm install
, os pacotes dependentes são instalados em node_modules
. Vamos dar uma olhada mais de perto no mecanismo específico pelo qual npm
instala pacotes dependentes em node_modules
.
Nas primeiras versões do npm
, a maneira npm
lidar com dependências era simples e rudimentar. Ele instalava dependências em seus respectivos node_modules
de maneira recursiva e estritamente de acordo com a estrutura package.json
e a estrutura package.json
dos pacotes de subdependência. Até que existam pacotes subdependentes que não dependam mais de outros módulos.
Por exemplo, nosso módulo my-app
agora depende de dois módulos: buffer
e ignore
:
{ "nome": "meu-aplicativo", "dependências": { "buffer": "^5.4.3", "ignorar": "^5.1.4", } }
ignore
é um módulo JS
puro que não depende de nenhum outro módulo, e buffer
depende dos dois módulos a seguir: base64-js
e ieee754
.
{ "nome": "buffer", "dependências": { "base64-js": "^1.0.2", "ieee754": "^1.1.4" } }
Então, após executar npm install
, a estrutura de diretórios do módulo em node_modules
obtida é a seguinte:
As vantagens desta abordagem são óbvias. A estrutura de node_modules
corresponde à estrutura de package.json
individualmente, a estrutura hierárquica é óbvia e a estrutura de diretório de cada instalação é garantidamente a mesma.
Porém, imagine só, se você depender de muitos módulos, seu node_modules
será muito grande e o nível de aninhamento será muito profundo:
Windows
, o comprimento máximo do caminho do arquivo é de 260 caracteres e um nível de aninhamento muito profundo pode causar problemas imprevisíveis.Para resolver os problemas acima, NPM
fez uma grande atualização na versão 3.x
Ele altera a estrutura aninhada inicial para uma estrutura plana:
node_modules
.Ainda com a estrutura de dependência acima, obteremos a seguinte estrutura de diretórios após executar npm install
:
Neste momento, se confiarmos na versão [email protected]
no módulo:
{ "Nome": "My-App", "dependências": { "Buffer": "^5.4.3", "Ignore": "^5.1.4", "base64-js": "1.0.1", } }
node_modules
a versão do módulo instalada corresponde ao intervalo de versão do novo módulo.Neste ponto, obteremos a seguinte estrutura de diretório após a execução de npm install
:
Do mesmo modo, se referenciarmos um módulo no código do projeto, o processo de pesquisa do módulo é o seguinte:
node_modules
node_modules
node_modules
caminho global é[email protected]
buffer2@^5.4.3
Portanto, a versão npm 3.x
não resolve completamente o problema de redundância do módulo da versão antiga e pode até trazer novos problemas.
Imagine que seu aplicativo não depende da versão [email protected]
, mas você também depende do buffer
e buffer2
que dependem de diferentes versões base64-js
. Desde que, ao executar npm install
, as dependências no package.json
são analisadas em ordem, a ordem em que buffer
e buffer2
são colocados no package.json
determina a estrutura de dependência de node_modules
:
depende do buffer2
primeiro:
Depende do buffer
primeiro:
Além disso, para permitir que os desenvolvedores usem os mais recentes pacotes de dependência sob a premissa de segurança, geralmente travamos apenas a versão grande no package.json
, o que significa que, após a versão menor de alguns pacotes de dependência, é atualizada, a estrutura de dependência pode também mudar.
para resolver o problema da incerteza da npm install
, o arquivo package-lock.json
foi adicionado na versão npm 5.x
, e o método de instalação também segue o método plano do npm 3.x
A função do package-lock.json
package-lock.json
bloquear a estrutura de node_modules
npm install
.
Por exemplo, temos a seguinte estrutura de dependência:
{ "Nome": "My-App", "dependências": { "Buffer": "^5.4.3", "Ignore": "^5.1.4", "base64-js": "1.0.1", } }
package-lock.json
gerado após a execução npm install
é o seguinte:
{ "Nome": "My-App", "versão": "1.0.0", "dependências": { "base64-js": { "versão": "1.0.1", "Resolvido": "https://registry.npmjs.org/base64-js/-/base64-js-1.0.1.tgz", "Integrity": "sha1-asbrszt7xze47tutdw3i/np+pag =" }, "Buffer": { "versão": "5.4.3", "Resolvido": "https://registry.npmjs.org/buffer/-/buffer-5.4.3.tgz", "Integrity": "SHA512-ZVJ65TKFEIT3I6AJ5BIVJDZJJQQGS4O/SNoezg1f1kyap9nu2jcudpwzrsjthmzg0h7bzkkn4rnqpimhuxx2a ==", ", "requer": { "base64-js": "^1.0.2", "IEEE754": "^1.1.4" }, "dependências": { "base64-js": { "versão": "1.3.1", "Resolvido": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", "Integridade": "SHA512-MLQ4I2QO1YTVGWFWMCNGKO // JXAQUEZVWEKTJGQFM4JIK0KU+YTMFPLL8J+N5MSPOFJHWOAG+9YHB7BWAHM36G ==" } } }, "IEEE754": { "versão": "1.1.13", "Resolvido": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", "Integrity": "SHA512-4VF7I2LYV/HAWERSO3XMLMKP5EZ83I+/CDLUXI/IGTS/O1SEJBNHTTNXZMRZFVOUQJ7LZJQHKETVPGSFDLWZTG ==" }, "Ignore": { "versão": "5.1.4", "Resolvido": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz", "Integridade": "SHA512-MZBUSAHKTW1U7JPKKJY7LCARD1FU5W2RLDXLM4KDKAYUCWZIMJKPLUF9CM1ALEWYJGUPDQEWlam18Y6AU69A8A ==" } } }
Vamos dar uma olhada na estrutura acima:
Os dois atributos mais externos name
e version
são os mesmos que name
e version
no package.json
e são usados para descrever o nome e a versão do pacote atual.
dependencies
é key
objeto, que corresponde à estrutura do node_modules
resolved
version
node_modules
dependencies
requires
integrity
hash
Subresource Integrity
foi modificado ou inválido.package.json
.dependencies
: a estrutura é a mesma que a estrutura dependencies
externas e armazena os pacotes de dependência instalados nos node_modules
de sub-dependência.Observe aqui que nem todas as sub-dependências têm o atributo dependencies
node_modules
Por exemplo, revise as dependências acima:
A versão [email protected]
em que confiamos no my-app
entra em conflito com base64-js@^1.0.2
em que confiamos no buffer
, portanto, [email protected]
precisa ser instalado nos node_modules
of the O pacote buffer
, correspondente ao atributo dependencies
do buffer
no package-lock.json
foi alterado. Isso também corresponde à abordagem plana das dependências da npm
.
Portanto, de acordo com a análise acima, package-lock.json
package-lock.json
node_modules
estão em correspondência individual. gerado por cada instalação da mesma forma.
Além disso, o uso do package-lock.json
no projeto pode acelerar significativamente o tempo de instalação de dependência.
Usamos o comando npm i --timing=true --loglevel=verbose
lock
lock
o processo completo da npm install
. Limpe o cache npm
antes de comparar.
Sem usar o arquivo lock
:
Use o arquivo lock
:
Pode-se observar que a versão específica e o link de download de cada pacote foram armazenados em cache no package-lock.json
. grande número de solicitações de rede.
para desenvolver aplicativos do sistema, é recomendável enviar o arquivo package-lock.json
ao repositório da versão do código para garantir que as versões de dependência instaladas por todos os desenvolvedores da equipe e links CI
sejam consistentes ao executar npm install
.
Ao desenvolver semver
pacote npm
, seu pacote npm
precisa depender de outros repositórios dentro do escopo, que causará redundância desnecessária. Portanto, não devemos publicar o arquivo package-lock.json
( npm
não publicará package-lock.json
por padrão).
depois de executar o comando npm install
ou npm update
para baixar dependências, além de instalar o pacote de dependência no diretório node_modules
, uma cópia também será armazenada em cache no diretório de cache local.
Você pode consultá -lo através npm config get cache
: No Linux
ou Mac
o padrão é o diretório .npm/_cacache
no diretório inicial do usuário.
Existem tar
diretórios neste diretório hash
content-v2
content-v2
e index-v5
tar
index-v5
Quando o NPM está executando a instalação, ele pode gerar uma key
exclusiva correspondente ao registro do cache no diretório index-v5
com base integrity、version、name
armazenado em package-lock.json
, encontrando assim hash
do pacote tar
, e depois procurando com base no hash
tar
Podemos encontrar um pacote para pesquisar e testar no diretório do cache e pesquisar o caminho do pacote no index-v5
:
grep "https://registry.npmjs.org/base64-js/-/base64-js-1.0.1. TGZ "-R Index -V5
Então formatamos o JSON:
{ "Key": "Pacote: Version-manifest: https: //registry.npmjs.org/base64-js/-/base64-js-1.0.1.tgz: sha1-asbrszt7xze47tutdw3i/np+pag =",,,, "Integridade": "SHA512-C2EKHXWXVLSBRUCJTRS3XFHV7MF/Y9KLMKDXPTE8YEVCOH5H8AE69Y+/LP+AHPW91CRNZGO78ELOK2E6APJFIQ ==", "Time": 1575554308857, "Tamanho": 1, "Metadata": { "ID": "[email protected]", "manifesto": { "Nome": "base64-js", "versão": "1.0.1", "Motores": { "Nó": "> = 0,4" }, "Dependências": {}, "OptionalDependências": {}, "DevDependências": { "padrão": "^5.2.2", "Fita": "4.x" }, "BundleDependências": false, "Peerdependências": {}, "depreciado": falso, "_Resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.0.1.tgz", "_integrity": "sha1-asbrszt7xze47tutdw3i/np+pag =", "_shasum": "6926D1B194FBC737B8EED513756DE2FCDA7EA408", "_shrinkwrap": null, "bin": nulo, "_id": "[email protected]" }, "Type": "Finalized-manifest" } }
O atributo _shasum
acima 6926d1b194fbc737b8eed513756de2fcda7ea408
é hash
do pacote tar
, e os primeiros dígitos 6926
do hash
são os dois primeiros níveis de pêlos em cache.
A estratégia de cache acima começa na versão NPM V5. }.
npm
fornece vários comandos para gerenciar dados de cache:
npm cache add
: A explicação oficial é que esse comando é usado principalmente internamente pelo npm
, mas também pode ser usado para adicionar manualmente um cache a um pacote especificado.npm cache clean
: Exclua todos os dados no diretório de cache --force
npm cache verify
: Verifique a validade e a integridade dos dados em cache e limpe os dados junk.Com base em dados em cache, o NPM fornece modos de instalação offline, que são os seguintes:
--prefer-offline
: Use os dados em cache primeiro.--prefer-online
: Priorize o uso de dados de rede.--offline
: não solicite a rede e use os dados em cache diretamente.mencionamos a integridade do arquivo muitas vezes acima, então o que é a verificação da integridade do arquivo?
Antes de baixar o pacote tarball
npm info
, shasum
podemos hash
hash
calculado pelo npm
para o pacote de dependência.
hash
que o usuário baixa o pacote de dependência localmente, ele ou ela precisa garantir que não ocorram hash
durante o processo de download. São iguais, verifique se a dependência baixada está completa.
Agora que o processo geral está concluído, vamos resumir o processo acima:
verifique o arquivo .npmrc
: a prioridade é: arquivo .npmrc
de nível de projeto> arquivo .npmrc
> arquivo global .npmrc
> npm interno interno .npmrc
Verifique se existe um arquivo lock
no projeto.
Sem arquivo lock
:
npm
package.json
. node_modules
.node_modules
do módulo atual.npm
o pacote de download de armazém remotonpm
node_modules
de acordo com a estrutura de dependêncialock
node_modules
node_modules
acordo com a estruturalock
package.json
package-lock.json
.O processo acima descreve brevemente o processo geral da npm install
npm install package --timing=true --loglevel=verbose
processo de instalação e detalhes de um determinado pacote.
yarn
foi lançado em 2016
Naquela época, package-lock.json
npm
ainda estava no período V3
. de desenvolvedores. Neste ponto, nasce yarn
:
O exposto acima são as vantagens do yarn
mencionado no site oficial, que ainda eram muito atraentes naquele momento. Obviamente, lock
npm
mais tarde realizou yarn
yarn
problemas e fez muitas otimizações. O design ainda é muito bom.
V3
yarn
npm v3
yarn.lock
yarn.lock
É um arquivo autogenerado. # fio de bloqueio v1 [email protected]: Versão "1.0.1" Resolveu-se "https://registry.yarnpkg.com/base64-js/-/base64-js-1.0.1.tgz#6926d1b194fbc737b8eed513756de2fcda7ea408" Integridade SHA1-ASBRSZT7XZE47TUTDW3I/NP+PAG = base64- js@^1.0.2: Versão "1.3.1" Resolvido "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ce8cb75dd07e71ed08c736abc5fac4dbf8df1" Integridade sha512-mlq4i2qo1ytvgwfwmcngko // jxaquezvwektjgqfm4jik0ku+ytmfpll8j+n5mspofjhwoag+9yhb7bwahm36g == buffer@^5.4.3: Versão "5.4.3" Resolvido "https://registry.yarnpkg.com/buffer/-/buffer-4.4.3.tgz#3fbc9c69eb713d323e3fc1a895eee0710c072115" Integridade SHA512-ZVJ65TKFEIT3I6AJ5BIVJDZJJJQGS4O/SNoezg1f1kyap9nu2jcudpwzrsjthmmzg0h7bzkn4rnqpimhuxwx2a == dependências: base64-js "^1.0.2" IEEE754 "^1.1.4" ieee754@^1.1.4: Versão "1.1.13" Resolvido "https://registry.yarnpkg.com/ieee754/-ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbbbb6708b84" Integridade SHA512-4VF7I2LYV/HAWERSO3XMLMKP5EZ83I+/CDLUXI/IGTS/O1SEJBNHTTNXZMRZFVOUQJ7LZJQHKETVPGSFDLWZTG == ignore@^5.1.4: Versão "5.1.4" Resolvido "https://registry.yarnpkg.com/ignore/-/ignore-5.1.4.tgz#84b7b3dbe64552b6ef0eca99f6743dbec6d97adf" Integridade SHA512-MZBUSAHKTW1U7JPKKJY7LCARD1FU5W2RLDXLM4KDKAYUCWZIMJKPLUF9CM1AlEWYJGUPDQUM18YSTONATONATOMENTE
json
package-lock.json
yarn.lock
yarn.lock
package-lock.json
yarn.lock
não é fixa, o que significa que yarn.lock
sozinho não pode determinar node_modules
e precisa ser coordenado com o arquivo package.json
. E package-lock.json
precisa apenas de um arquivo para determinar.A estratégia de cache do yarn
parece muito semelhante à do npm v5
. Use o yarn cache dir
de comando para visualizar o diretório de dados em cache:
Por padrão,
yarn
usa o modoprefer-online
, o que significa que os dados da rede são usados primeiro.
Espero que, depois de ler este artigo, ele o ajude a seguir:
npm
pacakge.json
para ter mais informações sobre a configuração de engenharia do projeto.npm
npm install
package-lock.json