web-dev-qa-db-fra.com

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

Je viens de passer à npm @ 5. J'ai maintenant un fichier package-lock.json avec tout ce qui est package.json. Lorsque j’exécutais npm install, les versions de dépendance seraient extraites du fichier de verrouillage pour déterminer les éléments à installer dans mon répertoire node_modules. Ce qui est étrange, c’est qu’il finit par modifier et réécrire mon fichier package-lock.json.

Par exemple, le fichier de verrouillage avait TypeScript spécifié comme étant à la version 2.1.6. Ensuite, après la commande 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 en sorte que npm respecte réellement mon fichier de verrouillage?

385
Viper Bailey

Mise à jour 3: Comme d'autres réponses le soulignent également, la commande npm ci a été introduite dans npm 5.7.0 en tant que moyen supplémentaire de créer des constructions rapides et reproductibles dans le contexte de CI. Voir le documentation et npm blog pour plus d'informations.


Mise à jour 2: Le problème pour mettre à jour et clarifier la documentation est Le numéro GitHub n ° 18103 .


Mise à jour 1: Le comportement décrit ci-dessous a été corrigé dans npm 5.4.2: le comportement actuellement souhaité est décrit dans Le numéro GitHub n ° 17979 .


Réponse originale: Le comportement de package-lock.json a été modifié dans npm 5.1.0 comme indiqué dans numéro # 16866 . Le comportement que vous observez est apparemment voulu par npm à partir de la version 5.1.0.

Cela signifie que package.json peut remplacer package-lock.json chaque fois qu'une version plus récente est trouvée pour une dépendance dans package.json. Si vous souhaitez épingler efficacement vos dépendances, vous devez maintenant spécifier les versions sans préfixe, par exemple, vous devez les écrire sous la forme 1.2.0 au lieu de ~1.2.0 ou ^1.2.0. Ensuite, la combinaison de package.json et package-lock.json donnera des versions reproductibles. Pour être clair: package-lock.json seul ne verrouille plus les dépendances au niveau racine!

Que cette décision de conception soit bonne ou non est discutable, une discussion en cours résulte de cette confusion sur GitHub dans numéro # 17979 . (À mes yeux, c'est une décision discutable; au moins, le nom lock n'est plus vrai.)

Remarque supplémentaire: il existe également une restriction pour les registres qui ne prennent pas en charge les paquets immuables, par exemple lorsque vous extrayez les paquets directement à partir de GitHub au lieu de npmjs.org. Voir cette documentation sur les verrous de paquet pour plus d'explications.

280
jotaen

J'ai constaté qu'il y aurait une nouvelle version de npm 5.7.1 avec la nouvelle commande npm ci, à installer à partir de package-lock.json uniquement

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

Cela 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 se trouve dans votre fichier de verrouillage, il est également beaucoup plus rapide (2x-10x!) Que l'installation de npm lorsque vous ne commencez pas par node_modules.

Comme vous pouvez le déduire de son nom, nous nous attendons à ce que cela soit un avantage considérable 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 obtiennent des gains importants.

102
Ivan Shcherbakov

Utilisez le nouvellement introduit

npm ci

npm ci promet le plus d'avantages aux grandes équipes. Donner aux développeurs la possibilité de «signer» un verrou de package favorise une collaboration plus efficace entre de grandes équipes et la possibilité d'installer exactement ce qui est dans un fichier verrou permet de gagner des dizaines, voire des centaines d'heures de développeur par mois, libérant ainsi les équipes. passer plus de temps à construire et à expédier des choses étonnantes.

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

59
Gal Margalit

Réponse courte:

  • Lorsque package-lock.json existe, il annule package.json
  • Lorsque package.json est modifié, il remplace le package-lock.json.

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

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

"depA": "^1.0.0"

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

"depA": "1.0.0"

Quelques jours plus tard, une version mineure plus récente de "depA" est publiée, par exemple "1.1.0".

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 à jour manuellement votre package.json pour:

"depA": "^1.1.0"

Puis relancez:

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)
9
Ahmad Abdelghany

Vous avez probablement quelque chose comme:

"TypeScript":"~2.1.6"

dans votre package.json qui met à jour npm vers la dernière version mineure, dans votre cas étant 2.4.1

Edit: Question de OP

Mais cela n'explique pas pourquoi "npm install" changerait le fichier de verrouillage. Le fichier de verrouillage ne vise-t-il pas à créer une version reproductible? Si c'est le cas, quelle que soit la valeur semver, il devrait toujours utiliser le même 2.1.6 version.

Réponse:

Ceci est destiné à verrouiller votre arbre de dépendance complet. Disons que TypeScript v2.4.1 nécessite widget ~v1.0.0. Lorsque vous npm l’installez saisit widget v1.0.0. Plus tard, votre collègue développeur (ou build CI) effectue une installation npm et obtient TypeScript v2.4.1 mais widget a été mis à jour à widget v1.0.1. Maintenant, votre module de noeud est désynchronisé. Ce est ce que package-lock.json empêche.

Ou plus généralement:

À titre d'exemple, considérons 

paquet A:

{"name": "A", "version": "0.1.0", "dépendances": { "B": "<0.1.0"}} 

paquet B:

{"name": "B", "version": "0.0.1", "dépendances": { "C": "<0.1.0"}}

et le paquet C:

{"nom": "C", "version": "0.0.1"}

Si ce sont les seules versions A, B et C disponibles dans le registre, puis une installation normale de npm A va installer:

[email protected] - [email protected] - [email protected] 

Toutefois, si [email protected] est publié, une nouvelle installation A de npm s’installera:

[email protected] - [email protected] - [email protected] en supposant que la nouvelle version ne modifie pas les dépendances de B. Bien entendu, la nouvelle version de B pourrait inclure un nouveau fichier version de C et un nombre quelconque de nouvelles dépendances. Si de tels changements sont indésirable, l'auteur de A pourrait spécifier une dépendance à [email protected] . Cependant, si l'auteur de A et l'auteur de B ne sont pas la même personne, il y a aucun moyen pour l'auteur de A de dire qu'il ou elle ne veut pas intervenir les nouvelles versions de C lorsque B n’a pas changé du tout.


Question 2 de l'OP: Laissez-moi voir si je comprends bien. Ce que tu es Ce qui est dit, c'est que le fichier de verrouillage spécifie les versions du fichier secondaire dépendances, mais repose toujours sur la correspondance floue de package.json pour déterminer les dépendances de niveau supérieur. Est-ce exact?

Réponse: Non. Package-lock verrouille toute l'arborescence du package, y compris le fichier Les packages racine décrits dans package.json. Si TypeScript est verrouillé à 2.4.1 dans votre package-lock.json, il devrait le rester jusqu'à ce que ce soit modifié. Et disons que demain TypeScript publie la version 2.4.2. Si j'achète votre branche et exécute npm install, npm respectera le lockfile et installer 2.4.1.

Plus sur package-lock.json:

package-lock.json est automatiquement généré pour toutes les opérations où npm modifie l'arborescence node_modules ou package.json. Il décrit l'arborescence exacte générée, de sorte que les installations ultérieures puissent générer des arborescences identiques, quelles que soient les mises à jour de dépendance intermédiaires.

Ce fichier est destiné à être validé dans les référentiels sources et sert à plusieurs fins:

Décrivez une représentation unique d'un arbre de dépendance de sorte que les coéquipiers, les déploiements et l'intégration continue soient garantis pour installer exactement les mêmes dépendances.

Fournissez aux utilisateurs une possibilité de "voyager dans le temps" vers les états précédents de node_modules sans avoir à valider le répertoire lui-même.

Pour faciliter une plus grande visibilité des modifications d'arborescence via des différences de contrôle de source lisibles.

Optimisez également le processus d’installation en permettant à npm d’ignorer les résolutions de métadonnées répétées pour les packages précédemment installés.

https://docs.npmjs.com/files/package-lock.json

6
Matt

Utilisez la commande npm ci au lieu de npm install.

"ci" signifie "installation propre". Il installera les dépendances du projet basées sur le fichier package-lock.json au lieu des dépendances indulgentes du fichier package.json.

Il produira des versions identiques à celles de vos autres coéquipiers et sera également beaucoup plus rapide.

5
Daniel Tonon

À l'avenir, vous pourrez utiliser un indicateur --from-lock-file (ou similaire) pour installer uniquement à partir du package-lock.json sans le modifier. 

Cela sera utile pour les environnements CI, etc., où des versions reproductibles sont importantes.

Voir https://github.com/npm/npm/issues/18286 pour le suivi de la fonctionnalité.

5

Il semble que ce problème soit résolu dans npm v5.4.2

https://github.com/npm/npm/issues/17979

(Faites défiler jusqu'au dernier commentaire du fil de discussion)

Mettre à jour

Actuellement corrigé dans 5.6.0. Un bogue multi-plateforme dans 5.4.2 était à l'origine du problème.

https://github.com/npm/npm/issues/18712

Mise à jour 2

Voir ma réponse ici: https://stackoverflow.com/a/53680257/1611058

npm ci est la commande que vous devez utiliser lorsque vous installez des projets existants maintenant.

3
Daniel Tonon

Il y a un numéro en suspens à ce sujet sur la page github: https://github.com/npm/npm/issues/18712

Ce problème est plus grave lorsque les développeurs utilisent différents systèmes d'exploitation.

1
hrdwdmrbl

EDIT: le nom "lock" est délicat, son NPM essayant de rattraper Yarn. Ce n'est pas un fichier verrouillé que ce soit. package.json est un fichier fixé par l'utilisateur, qui une fois "installé" générera une arborescence de dossiers node_modules et cette arborescence sera alors écrite en package-lock.json. Donc, vous voyez, c'est l'inverse: les versions de dépendance seront extraites de package.json comme toujours, et package-lock.json devrait s'appeler package-tree.json

(J'espère que cela a clarifié ma réponse, après tant de votes négatifs)


Une réponse simpliste: package.json a vos dépendances comme d'habitude, tandis que package-lock.json est "une arborescence de nœuds_modules exacte et, surtout, reproductible" (tiré de npm docs lui-même ).

Quant au nom difficile, son NMP essaye de rattraper Yarn.

0
Z. Khullah