Comment le package-lock.json a sauvé mes vacances

La première fois que j’ai travaillé en équipe, ça a été le fiasco total !

Aucun des deux développeurs avec lesquels je travaillais n’a réussi à démarrer le projet que je réalisais.

Le hic, c’est que je partais en vacances et il fallait que mes collègues puissent le reprendre pour continuer sans moi.

De mon côté, c’était l’éternel :

« Je ne comprends pas, ça marche sur ma machine ! »

Que s’est il passé ?

C’était il y a quelques années, NPM, le gestionnaire de dépendances JavaScript venait de passer en version 5, et avec lui, l’ajout d’une fonctionnalité de marque : le fichier de verrouillage des dépendances (le fameux « package-lock.json »).

C’est une fonctionnalité qui permet de figer l’arbre des dépendances installées et de reproduire cette installation à l’identique autant de fois que nécessaire.

Comment ça marche ?

Supposons que vous souhaitez installer la dépendance « axios » (un client HTTP) dans votre super application.

Vous allez taper la commande suivante dans votre terminal :

npm install axios

Votre fichier « package.json » contiendra alors l’information suivante :

{
  "name": "my-super-app",
  "version": "1.0.0",
  "license": "UNLICENSED",
  "dependencies": {
    "axios": "^0.21.1"
  }
}

Et votre fichier « package-lock.json » contiendra quelque chose comme ça :

{
  "name": "my-super-app",
  "version": "1.0.0",
  "lockfileVersion": 1,
  "requires": true,
  "dependencies": {
    "axios": {
      "version": "0.21.1",
      "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
      "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
      "requires": { "follow-redirects": "^1.10.0" }
     },
    "follow-redirects": {
      "version": "1.14.1",
      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz",
      "integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg=="
     }
  }
}

Le fichier de verrouillage va stocker la version exacte installée à cet instant de axios (même si votre « package.json » autorise plusieurs versions) avec l’URL de téléchargement et la signature de la dépendance installée.

Et surtout, le plus important, il va faire la même chose avec les dépendances de vos dépendances (ce que l’on appelle les dépendances transitives).

Dans notre exemple, axios dépend du paquet « follow-redirects » (il en a besoin pour fonctionner), ce dernier va donc également se retrouver dans ce fameux « package-lock.json » avec une version figée, même si axios en accepte plusieurs dans son propre fichier « package.json ».

La prochaine fois que vous ferez un ‘npm install’, NPM utilisera le fichier de verrouillage pour reproduire la même installation (il suffira d’aller chercher les URL sauvegardées à l’intérieur).

NPM peut ensuite vérifier que c’est toujours exactement la même chose qui est installé en calculant la signature de la dépendance installée et en la comparant à celle du fichier de verrouillage.

Ce mécanisme permet de garantir que votre installation de dépendances est reproductible.

Sauf que, quand NPM s’est mis à jour sur ma machine, la seule chose que j’ai constaté, c’est qu’un nouveau fichier généré – que je n’avais pas demandé (le fameux package-lock.json) – était apparu et venait poluer mon beau projet.

Comme je ne comprenais pas ce package-lock.json, j’ai trouvé la configuration me permettant de m’en débarrasser et de retourner à mes petites habitudes bien rangées en deux temps trois mouvements (il suffit de créer un fichier « .npmrc » à la racine de votre répertoire de travail avec la configuration suivante).

package-lock=false

Le problème, c’est que certaines dépendances transitives avaient été mises à jour entre le moment où j’avais fait mon installation et celui où mes collègues l’ont effectué.

Et pas de bol, l’une d’entre elle avait introduit un changement cassant, autorisant notre dépendance directe à l’installer.

Sans le fichier de verrouillage pour figer la version qui marchait pour moi, mes collègues n’étaient pas en mesure de reproduire une installation identique, et dans ce cas particulier, ne pouvait même plus lancer le projet à cause du changement cassant (une fonction avait été renommée) !

Le fichier de verrouillage est donc de nos jours un élément indispensable pour tous les projets, que l’on travaille seul ou à plusieurs, au vu du nombre exponentiellement grandissant de bibliothèques utilisées (ce qui est d’ailleurs un problème, si le sujet de la performance et de la lourdeur des logiciels vous intéresse, je vous recommande la lecture de ma traduction de l’excellent article de Nikita Prokopov : https://blog.romainfallet.fr/desenchantement-logiciel).

Dans mon cas, si j’avais supprimé mon dossier node_modules, j’aurais rencontré exactement le même problème que mes collègues en essayant de réinstaller mes dépendances.

Pour profiter des bienfaits du fichier de verrouillage il faut donc bien l’ajouter dans vos commits et l’envoyer sur votre dépôt Git.

C’est donc après quelques heures de recherche et une petite remise en question que je suis parvenu à remettre en place une installation reproductible après avoir rétrogradé la version du paquet qui posait problème.

J’ai pu ensuite partir sereinement en vacances !

Mais mais mais, on ne peut pas se quitter là-dessus…

Si les mainteneurs du paquet incriminé avaient suivi la spécification de gestion sémantique des versions (Semantic Versionning ou SemVer en anglais), tout ceci ne serait pas arrivé !

Qu’est-ce que c’est ? Ce sera le sujet du prochain article !

Abonnez-vous sur https://compagnon.artisandeveloppeur.fr/veille et les numéros de version n’auront plus de secret pour vous (très utile si vous ne connaissez pas la signification des « ^ » et « ~ » dans votre package.json ;)).

Au plaisir d’échanger !

Auteur/autrice : Romain Fallet

Lead developer chez tolk.ai. Ce qui fait me fait vibrer : l'excellence technique, l’agilité poussée à son paroxysme et la protection de la vie privée. Partisan d'un web plus simple et plus éthique. Ouvert aux échanges et aux discussions !

4 réflexions sur « Comment le package-lock.json a sauvé mes vacances »

  1. A préciser que depuis une certaine version de NPM, ce dernier ne prend plus en compte le package-lock.json pendant un nom install.

    La seule manière propre de récupérer les dépendances correspondantes au package-lock.json est d’utiliser la commande npm ci.

      1. Ça doit dépendre de la version de NPM, en effet. J’utilise une version 6 embarquée dans la 14 LTS de Node.

        Ce que j’ai constaté, c’est qu’un npm install modifie le package-lock.json et peut mettre à jour des dépendances alors qu’un npm ci applique bêtement le contenu du package-lock.json. Cf. ici : https://stackoverflow.com/questions/45022048/why-does-npm-install-rewrite-package-lock-json

        A noter tout de même que la commande npm ci est recommandée pour avoir un environnement iso de manière plus rapide que npm install : https://blog.npmjs.org/post/171556855892/introducing-npm-ci-for-faster-more-reliable

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.