945 votes

Pourquoi "npm install" réécrit-il le fichier package-lock.json ?

J'ai récemment mis à niveau vers npm@5 . J'ai maintenant un paquet-lock.json avec tous les éléments de paquet.json . Je m'attendrais à ce que, lorsque j'exécute npm install que les versions des dépendances seraient extraites du fichier de verrouillage pour déterminer ce qui doit être installé dans mon modules de nœuds répertoire. Ce qui est étrange, c'est qu'il finit par modifier et réécrire mon fichier paquet-lock.json fichier.

Par exemple, le fichier de verrouillage avait spécifié que le typecript était à la version 2.1.6 . Puis, après le npm install la version a été modifiée en 2.4.1 . Cela semble aller à l'encontre de l'objectif d'un fichier de verrouillage.

Qu'est-ce que je rate ? Comment faire pour que npm respecte réellement mon fichier de verrouillage ?

8 votes

Cela ne répond pas à votre question, alors j'espère qu'un commentaire est acceptable, mais jetez un coup d'œil à Yarn. Le changement a pris moins d'une heure pour nous.

9 votes

Le même problème mais en utilisant du fil github.com/yarnpkg/yarn/issues/570 (très instructif)

5 votes

J'ai le même problème. Mon package-lock.json se régénère lorsque je lance npm install . Cela sent le bug de NPM. Utilisez-vous votre propre registre ?

632voto

jotaen Points 3934

Mise à jour 3 : Comme d'autres réponses le soulignent également, le npm ci a été introduite dans npm 5.7.0 comme un moyen supplémentaire de réaliser des constructions rapides et reproductibles dans le contexte CI. Voir le documentation y le blog npm pour de plus amples informations.


Mise à jour 2 : La question de la mise à jour et de la clarification de la documentation est Problème GitHub #18103 .


Mise à jour 1 : Le comportement décrit ci-dessous a été corrigé dans npm 5.4.2 : le comportement actuellement prévu est décrit dans Problème GitHub #17979 .


Réponse originale : Le comportement de package-lock.json a été modifié en npm 5.1.0 tel que discuté dans numéro 16866 . Le comportement que vous observez est apparemment prévu par npm à partir de la version 5.1.0.

Cela signifie que package.json peut passer outre package-lock.json chaque fois qu'une version plus récente est trouvée pour une dépendance dans package.json . Si vous voulez épingler vos dépendances de manière efficace, vous devez maintenant spécifier les versions sans préfixe, par exemple, vous devez les écrire comme suit 1.2.0 au lieu de ~1.2.0 ou ^1.2.0 . Alors la combinaison de package.json y package-lock.json permettra d'obtenir des constructions reproductibles. Pour être clair : package-lock.json seul ne verrouille plus les dépendances du niveau Root !

Que cette décision de conception soit bonne ou non est discutable, il y a une discussion en cours résultant de cette confusion sur GitHub en numéro 17979 . (A mes yeux, c'est une décision discutable ; au moins le nom lock n'est plus valable aujourd'hui).

Autre remarque : il existe également une restriction pour les registres qui ne prennent pas en charge les paquets immuables, par exemple lorsque vous tirez des paquets directement de GitHub au lieu de npmjs.org. Voir cette documentation sur les verrous de paquets pour plus d'explications.

0 votes

C'est une longue discussion, donc je ne serais pas surpris que le comportement change à l'avenir. Pour l'instant, ce commentaire confirme également votre conseil, à savoir que les versions en package.json doit également être verrouillé.

1 votes

Au fait, une fois que vous avez tout verrouillé, si vous voulez essayer des versions plus récentes de vos dépendances, il y a un outil sympa appelé updtr qui peut y contribuer.

83 votes

Ce qu'est le hack npm update pour alors ? :o J'ai eu le même sentiment que npm install mis à jour deps, mais je ne veux pas le croire mais il semble que c'est tristement vrai De toute façon, il y a toujours la possibilité d'utiliser npm shrinkwrap pour verrouiller les deps, mais le nom définitif package-lock est incorrect car il ne gèle pas, ni ne verrouille les dépendances .

249voto

Ivan Shcherbakov Points 1479

J'ai découvert qu'il y aura une nouvelle version de npm 5.7.1 avec la nouvelle commande npm ci qui s'installera à partir de package-lock.json sólo

La nouvelle commande npm ci installe à partir de votre fichier de verrouillage UNIQUEMENT. Si votre package.json et votre fichier lock ne sont pas synchronisés, une erreur sera signalée.

Il fonctionne en jetant vos node_modules et en les recréant à partir de zéro.

En plus de vous garantir que vous n'obtiendrez que ce qui est dans votre fichier lock, il est également beaucoup plus rapide (2x-10x !) que npm install lorsque vous ne commencez pas avec un node_modules.

Comme son nom l'indique, nous nous attendons à ce qu'il soit un atout majeur pour les environnements d'intégration continue. Nous nous attendons également à ce que les personnes qui effectuent des déploiements de production à partir de balises git en retirent des avantages majeurs.

216 votes

Ceci devrait être le comportement par défaut si un fichier de verrouillage existe.

19 votes

Ils ont donc changé le fonctionnement de npm i, pour le ramener en tant que npm ci quelques mois plus tard ?

0 votes

Tous les projets ne disposent pas d'un fichier de verrouillage, donc je suppose que la meilleure façon d'initialiser un repo arbitraire que vous avez téléchargé est la suivante npm ci || npm i

183voto

Réponse courte :

  • npm install honore package-lock.json uniquement s'il satisfait aux exigences de package.json.
  • S'il ne satisfait pas à ces exigences, les paquets sont mis à jour et le verrouillage des paquets est écrasé.
  • Si vous voulez que l'installation échoue au lieu d'écraser le verrouillage du paquet lorsque cela se produit, utilisez npm ci .

Voici un scénario qui pourrait expliquer les choses (vérifié avec NPM 6.3.0)

Vous déclarez une dépendance dans package.json comme :

"depA": "^1.0.0"

Alors vous le faites, npm install qui générera un package-lock.json avec :

"depA": "1.0.0"

Quelques jours plus tard, une nouvelle version mineure de "depA" est publiée, disons "1.1.0", et ce qui suit est vrai :

npm ci       # respects only package-lock.json and installs 1.0.0

npm install  # also, respects the package-lock version and keeps 1.0.0 installed 
             # (i.e. when package-lock.json exists, it overrules package.json)

Ensuite, vous mettez manuellement à jour votre package.json pour :

"depA": "^1.1.0"

Puis rediffuser :

npm ci      # will try to honor package-lock which says 1.0.0
            # but that does not satisfy package.json requirement of "^1.1.0" 
            # so it would throw an error 

npm install # installs "1.1.0" (as required by the updated package.json)
            # also rewrites package-lock.json version to "1.1.0"
            # (i.e. when package.json is modified, it overrules the package-lock.json)

10 votes

C'est en effet le comportement attendu d'un fichier "lock". Apparemment, ce n'était pas le cas avec les anciennes versions de NPM.

1 votes

Alors comment npm suit-il la dernière mise à jour du package.json ? Que se passe-t-il lorsque vous déplacez votre package.json et votre package-lock.json sur un autre ordinateur ? Comment npm peut-il savoir si le package.lock est l'original ou s'il a été mis à jour, pour décider s'il doit mettre à jour package-lock.json ou non ?

0 votes

Ce problème est maintenant résolu en ajoutant npm-shrinkwrap.json dont la syntaxe et le contenu sont exactement les mêmes que ceux du programme package-lock.json et prévoit la même fonctionnalité.

122voto

Gal Margalit Points 409

Utilisez le nouvel outil

npm ci

npm ci promet le plus d'avantages aux grandes équipes. Donner aux développeurs la possibilité de "signer" le verrouillage d'un paquet favorise une collaboration plus efficace au sein des grandes équipes, et la possibilité d'installer exactement ce qui est dans un fichier de verrouillage a le potentiel d'économiser des dizaines, voire des centaines d'heures de développement par mois, libérant ainsi les équipes pour qu'elles puissent passer plus de temps à construire et à expédier des choses étonnantes.

Présentation de npm ci pour des constructions plus rapides et plus fiables

5 votes

Cela me semble correct ? quelqu'un d'autre peut-il confirmer ?

9 votes

@phouse512 C'est exact. Nous avons à peu près sólo utiliser npm ci et n'utiliser que npm install si vous mettez à jour ou installez de nouveaux paquets.

1 votes

Commentaires récents, etc. C'est la réponse que je retiens. Dommage qu'ils n'aient pas pu réparer cet horrible problème, mais si le nouvel évangile est "npm ci", alors très bien. Je peux m'adapter.

42voto

Dan T Points 121

Utilisez le npm ci au lieu de npm install .

"ci" signifie "intégration continue".

Il installera les dépendances du projet en se basant sur le fichier package-lock.json au lieu des dépendances indulgentes du fichier package.json.

Il produira des constructions identiques à celles de vos coéquipiers et il est également beaucoup plus rapide.

Vous pouvez en savoir plus à ce sujet dans cet article de blog : https://blog.npmjs.org/post/171556855892/introducing-npm-ci-for-faster-more-reliable

7 votes

ci fait référence à l'"intégration continue", comme mentionné dans la documentation et l'article de blog annonçant la commande : blog.npmjs.org/post/171556855892/…

0 votes

Merci, Joe. J'ai mis à jour ma réponse avec le nom correct et le lien vers l'article du blog. (pour ceux qui lisent ceci, j'ai dit précédemment que cela signifiait "clean install")

3 votes

"Et il est aussi beaucoup plus rapide" - il va supprimer node_modules et le recréer à partir de zéro. Est-ce vraiment beaucoup plus rapide ? Est-ce que npm install supprimer node_modules dossier, aussi ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X