Pourquoi «npm install» réécrit package-lock.json?

Je viens juste de passer à npm @ 5. J’ai maintenant un fichier package-lock.json avec tout de package.json. Je m’attendrais à ce que, lorsque je lance npm install , les versions de dépendance seraient extraites du fichier de locking pour déterminer ce qui devrait être installé dans mon répertoire node_modules. Ce qui est étrange, c’est que cela finit par modifier et réécrire mon fichier package-lock.json.

Par exemple, le fichier de locking a été spécifié à la version 2.1.6. Ensuite, après la commande npm install , la version a été modifiée pour 2.4.1. Cela semble aller à l’encontre de la finalité d’un fichier de locking.

Qu’est-ce que je rate? Comment puis-je obtenir npm pour respecter réellement mon fichier de locking?

    Mise à jour 2: le problème pour mettre à jour et clarifier la documentation est le numéro 18103 de Github .


    Mise à jour 1: Le comportement décrit ci-dessous a été corrigé dans npm 5.4.2: le comportement actuel est décrit dans le numéro 17979 de Github .


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

    Cela signifie que package.json peut prendre le pas sur 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 efficacement vos dépendances, vous devez maintenant spécifier les versions sans préfixe, par exemple, vous devez les écrire en tant que 1.2.0 au lieu de ~1.2.0 ou ^1.2.0 . La combinaison package.json et package-lock.json produira alors 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, il y a une discussion en cours résultant de cette confusion sur Github dans le numéro 17979 . (À mes yeux, c’est une décision discutable, au moins le lock nom ne tient plus.)

    Une autre remarque: il existe également une ressortingction pour les registres qui ne prennent pas en charge les paquets immuables, par exemple lorsque vous extrayez des paquets directement depuis Github au lieu de npmjs.org. Voir cette documentation des verrous de paquet pour plus d’explications.

    J’ai trouvé qu’il y aura une nouvelle version de npm 5.7.1 avec la nouvelle commande npm ci , qui sera installée à partir de package-lock.json uniquement.

    La nouvelle commande npm ci s’installe à partir de votre fichier de locking UNIQUEMENT. Si votre package.json et votre fichier de locking ne sont pas synchronisés, ils signaleront une erreur.

    Cela fonctionne en jetant votre node_modules et en le recréant à partir de zéro.

    En plus de vous garantir que vous n’obtiendrez que ce qui se trouve dans votre fichier de locking, il est également beaucoup plus rapide (2x-10x!) Que npm install lorsque vous ne commencez pas par node_modules.

    Comme vous pouvez le voir sur le nom, nous pensons qu’il sera un grand avantage pour les environnements d’continuous integration. Nous nous attendons également à ce que les gens qui font des déploiements de production à partir de tags git obtiennent des gains importants.

    Utilisez le nouveau introduit

     npm ci 

    npm ci promet le plus d’avantages pour les grandes équipes. Donner aux développeurs la possibilité de «se déconnecter» sur un verrou de package favorise une collaboration plus efficace entre les grandes équipes et la possibilité d’installer exactement ce qu’il y a dans un fichier de locking peut sauver 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 incroyables.

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

    Vous avez probablement quelque chose comme:

     "typescript":"~2.1.6" 

    dans votre package.json quelles mises à jour npm à la dernière version mineure, dans votre cas 2.4.1

    Edit: Question de OP

    Mais cela n’explique pas pourquoi “npm install” changerait le fichier de locking. Le fichier de locking n’est-il pas destiné à créer une version reproductible? Si tel est le cas, quelle que soit la valeur du semver, il devrait toujours utiliser la même version 2.1.6.

    Répondre:

    Ceci est destiné à verrouiller votre arbre de dépendance complet. Disons que typescript v2.4.1 nécessite un widget ~v1.0.0 . Lorsque vous installez npm, il widget v1.0.0 . Plus tard, votre collègue développeur (ou la version CI) effectue une installation npm et obtient la typescript v2.4.1 mais le widget a été mis à jour avec le widget v1.0.1 . Maintenant, votre module de noeud est désynchronisé. C’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”, “dependencies”: {“B”: “<0.1.0"}}

    paquet B:

    {“name”: “B”, “version”: “0.0.1”, “dependencies”: {“C”: “<0.1.0"}}

    et paquet C:

    {“name”: “C”, “version”: “0.0.1”}

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

    A@0.1.0 – B@0.0.1 – C@0.0.1

    Cependant, si B@0.0.2 est publié, alors une nouvelle installation npm installera:

    A@0.1.0 – B@0.0.2 – C@0.0.1 en supposant que la nouvelle version ne modifie pas les dépendances de B. Bien entendu, la nouvelle version de B pourrait inclure une nouvelle version de C et un nombre quelconque de nouvelles dépendances. Si de telles modifications sont indésirables, l’auteur de A peut spécifier une dépendance sur B@0.0.1. Cependant, si l’auteur de A et l’auteur de B ne sont pas la même personne, l’auteur de A ne peut en aucun cas dire qu’il ne souhaite pas insérer de nouvelles versions de C lorsque B n’a pas du tout changé.


    OP Question 2: Alors laissez-moi voir si je comprends bien. Ce que vous dites, c’est que le fichier de locking spécifie les versions des dépendances secondaires, 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 des packages, y compris les packages racine décrits dans package.json . Si typescript est verrouillé en 2.4.1 dans votre package-lock.json , il doit restr ainsi jusqu’à ce qu’il soit modifié. Et disons que demain, la typescript publie la version 2.4.2 . Si je vérifie votre twig et lancez npm install , npm respectera le fichier de locking et installera 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, indépendamment des mises à jour de dépendances intermédiaires.

    Ce fichier est destiné à être envoyé dans des référentiels sources et sert à diverses fins:

    Décrire une représentation unique d’une arborescence de dépendances telle que les coéquipiers, les déploiements et l’continuous integration garantissent l’installation exacte des mêmes dépendances.

    Permet aux utilisateurs 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 changements d’arborescence via des différences de contrôle de source lisibles.

    Et optimisez le processus d’installation en autorisant npm à 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

    À l’avenir, vous pourrez utiliser un --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ù les builds reproductibles sont importants.

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

    Il y a un problème ouvert sur leur page github: https://github.com/npm/npm/issues/18712

    Ce problème est particulièrement grave lorsque les développeurs utilisent différents systèmes d’exploitation.

    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 dans le fil)

    Mettre à jour

    Effectivement fixé dans 5.6.0. Il y avait un bogue multi-plateforme dans la version 5.4.2 qui causait toujours le problème.

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

    EDIT: le nom “lock” est un nom délicat, son NPM essayant de rattraper Yarn. Ce n’est pas un fichier verrouillé que ce soit. package.json est un fichier fixe par l’utilisateur, qui une fois “installé” va générer une arborescence de fichiers node_modules et que cette arborescence sera alors écrite dans package-lock.json . Donc, vous voyez, c’est l’inverse – les versions de dépendances seront toujours extraites de package.json , et package-lock.json devrait s’appeler package-tree.json

    (j’espère que cela a rendu ma réponse plus claire, après tant de commentaires)


    Une réponse simpliste: package.json a vos dépendances comme d’habitude, alors que package-lock.json est “une package-lock.json exacte et surtout reproductible” (prise à partir de npm docs lui-même ).

    En ce qui concerne le nom délicat, son MNP essaie de rattraper Yarn.

    Cela semble également se produire avec npm6 – J’ai exécuté npm i sans rien changer, et mon package-lock.json été modifié (les versions de tous les paquets package-lock.json changent).

    Cela semble intentionnel et ne rien casser? Plus d’infos ici