Avec l’arrivée de la version 5 de NPM en 2017, plusieurs nouveaux outils furent distribués aux développeurs, tels que le nouveau package-lock.json. Comme ça fait plusieurs mois que je cherche une explication claire sur l’utilité de package-lock.json et que je n’ai jamais trouvé d’article concis qui l’explique de A-Z, j’ai décidé de partager ce que j’en avais compris après plusieurs heures d’investigation. Avec un peu de chance, l’article suivant vous sauvera ces heures!
Le problème
- npm install n’est pas déterministe. Si aujourd’hui j’exécute npminstall, et que demain j’exécute npminstall, je n’aurai peut-être pas le même résultat.
- Ce qui arrive, c’est que les bons vieux ~ et ^ dans package.json font en sorte que npminstallva parfois installer des versions plus récentes des packages listés dans package.json. Considérons la syntaxe 1.0.1 = major.minor.patchcomme étant la syntaxe utilisée pour gérer les versions des npm packages
- ~1.0.1: installe la version patch la plus récente pour cette version de minor. Donc ça peut inclure 1.0.2, 1.0.3, 1.0.4, ainsi de suite, mais PAS 1.1.0. TL;DR: met à jour le patch seulement, tant que la version du package reste à ce minor
- ^1.0.1 : même principe mais pour le minor Donc ça peut inclure 1.0.2, 1.0.3, 1.0.4, 1.1.0, 1.2.0, mais pas 2.0.0. TL;DR: upgrade le patch, le minor, tant que la version du package reste à ce major
La solution
- package-lock.json : aggrège une version immuable du package.json, de façon à ce que l’on puisse, par exemple, aller chercher du vieux code (qui contient une image immutable des packages utilisés à ce moment) et avoir le même node_modules comme extrant de npm install.
- package-lock.json est généré par npm install. Donc si npm install décide de mettre à jour un package, un nouveau package-lock.json sera généré. Celui-ci contient les packages les plus récents qui respectent les règles d’upgrade établies dans le package.json.
- avec le package-lock.json vient la belle commande npm ci. Elle fait exactement la même chose que npm install, mais avec package-lock.json au lieu de package.json.
En résumé
- npm installn’est pas déterministe, et génère un package-lock.json
- package-lock.json permet d’avoir un node_modules déterministe avec la commande npm ci.
- Rouler un npm ci sur un package-lock.json va TOUJOURS générer le MÊME node_modules
Pourquoi c’est important dans votre vie de dev?
- La beauté de la chose, c’est que maintenant, on peut mettre en cache notre dossier node_modules!!!
- On génère une clef de cache à partir du contenu de package-lock.json.
- Si notre package-lock.jsonn’a pas bougé depuis la dernière fois, on va aller chercher notre node_modules dans notre cache, et ainsi couper quelques minutes d’attente d’intégration! (yourmileagemayvary).
Annexe
Le temps d’installation est rendu quasiment nul !!
- task: Cache@2 inputs: key: '**/package-lock.json, !**/node_modules/**/package-lock.json, !**/.*/**/package-lock.json' path:$PATH_TO_YOUR_FRONTENDClientAppnode_modules' cacheHitVar: 'CacheRestored' - task: Npm@1 displayName: 'npm ci' condition: ne(variables['CacheRestored'], 'true') inputs: command: 'ci' workingDir: '$PATH_TO_YOUR_FRONTENDClientApp'